我试过工会......
struct foo
{
union
{
struct // 2 bytes
{
char var0_1;
};
struct // 5 bytes
{
char var1_1;
int var1_2;
};
};
};
问题:工会做我想做的事,除了它们总是采用最大数据类型的大小。在我的情况下,我需要struct foo进行一些初始化,允许我告诉它选择哪个结构(如果这是合法的),如下所示。
之后,我尝试了类模板重载...
template <bool B>
class foo { }
template <>
class foo<true>
{
char var1;
}
template <>
class foo<false>
{
char var0;
int var1;
}
问题:我对模板非常满意,并且我可以在char和int上使用相同的变量名,但问题在于语法。因为类是在编译时创建的,所以模板布尔变量需要是一个硬编码常量,但在我的情况下,布尔值需要在运行时用户定义。
所以我需要两个“世界”的东西。我怎样才能实现我想要做的事情?
!!注意:foo类/ struct稍后会被继承,因此如前所述,foo的大小至关重要。
EDIT#1 :: 应用程序:
基本上这将用于读/写(使用指针作为接口)特定的数据缓冲区,并且还允许我创建(类/ struct的新实例)相同的数据缓冲区。您在上面看到的变量指定长度。如果它是一个较小的数据缓冲区,则长度以char / byte写入。如果它是一个更大的数据缓冲区,则第一个char / byte为null作为标志,而int指定长度。在长度之后,显然实际数据如下,因此为什么继承。课程的大小是最重要的。我需要吃蛋糕然后吃。
答案 0 :(得分:1)
一个抽象层。
struct my_buffer_view{
std::size_t size()const{
if (!m_ptr)return 0;
if (*m_ptr)return *m_ptr;
return *reinterpret_cast<std::uint32_t const*>(m_ptr+1);
}
std::uint8_t const* data() const{
if(!m_ptr)return nullptr;
if(*m_ptr)return m_ptr+1;
return m_ptr+5;
}
std::uint8_t const* begin()const{return data();}
std::uint8_t const* end()const{return data()+size();}
my_buffer_view(std::uint_t const*ptr=nullptr):m_ptr(ptr){}
my_buffer_view(my_buffer_view const&)=default;
my_buffer_view& operator=(my_buffer_view const&)=default;
private:
std::uint8_t const* m_ptr=0;
};
任何地方都没有可变大小的数据。我已经使用size
etx的联盟:
struct header{
std::uint8_t short_len;
union {
struct{
std::uint32_t long_len;
std::uint8_t long_buf[1];
}
struct {
std::short_buf[1];
}
} body;
};
但我只是做了指针运算。
将这样的缓冲区写入字节流完全是另一个问题。
答案 1 :(得分:0)
您的解决方案没有意义。考虑一下你的解决方案:你可以定义两个独立的类:fooTrue和fooFalse,相应的成员完全具有相同的结果。
或许,您正在寻找一种不同的解决方案作为继承。例如,你的fooTrue是baseFoo,你的fooFalse是derivedFoo,前一个是base,并用另一个int成员扩展它。
在这种情况下,您将多态性作为在运行时工作的方法。
答案 2 :(得分:0)
你也不能吃蛋糕。
模板的重点是专业化发生在编译时。在运行时,类的大小是固定的(尽管是以实现定义的方式)。
如果您希望在运行时进行选择,则无法在编译时使用确定大小的机制。您将需要一种能够满足两种可能需求的机制。实际上,这意味着您的基类需要足够大才能包含所有必需的成员 - 这基本上是基于联合的解决方案所发生的事情。
参考您的&#34; !!注意&#34;。你所做的就是过早优化。您正在尝试优化基类的大小而没有任何证据(例如,内存使用量的测量),大小差异对于您的应用程序实际上是重要的(例如,它会导致应用程序耗尽可用内存)。事情是某些东西将成为许多其他类的基础,这本身就不足以担心它的大小。