Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/162.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在编译时动态生成结构_C++_Templates_C++11_Structure_Template Meta Programming - Fatal编程技术网

C++ 在编译时动态生成结构

C++ 在编译时动态生成结构,c++,templates,c++11,structure,template-meta-programming,C++,Templates,C++11,Structure,Template Meta Programming,我必须生成一个只在特定条件下包含特定字段的数据结构。这通常会转化为以下内容 struct MyStruct { int alwaysHere; #ifdef WHATEVER bool mightBeHere; #endif char somethingElse; #if SOME_CONSTANT > SOME_VALUE uint8_t alywasHereButDifferentSize; #else uint16_t

我必须生成一个只在特定条件下包含特定字段的数据结构。这通常会转化为以下内容

struct MyStruct {
    int     alwaysHere;

#ifdef WHATEVER
    bool    mightBeHere;
#endif

    char    somethingElse;

#if SOME_CONSTANT > SOME_VALUE
    uint8_t alywasHereButDifferentSize;
#else
    uint16_t alywasHereButDifferentSize;
#endif
...
};
在我看来,这很容易让人看得难看,看不懂。 甚至不讨论处理这些字段的代码,通常在 伊夫迪夫也是

我正在寻找一种优雅的方法来实现相同的结果,而不增加任何开销,但代码太复杂 更具可读性。模板专门化似乎有点过分,但在我看来 这是唯一的选择

C++11是否添加了任何东西来处理这种情况


如果您有任何建议,我们将不胜感激。

我已经看到工会已经完成了这项工作(http://www.cplusplus.com/doc/tutorial/other_data_types/),但我不确定具体细节,因为我自己从未实施过。与第二个macrohackery不同,您将拥有:

union {
  uint8_t alywasHereButDifferentSize;
  uint16_t alywasHereButDifferentSize;
}
当引用时,您会有一个if,它引用了一个或另一个变量


或者,您可以创建一个void*指针,在运行时初始化该指针,指向任意一种类型的变量。

第二种情况可以替换为

std::conditional<(SOME_CONSTANT > SOME_VALUE), uint8_t, uint16_t>::type
alywasHereButDifferentSize;
std::conditional SOME\u VALUE),uint8\u t,uint16\u t>::类型
总是不同的大小;
首先,我认为没有。

首先:

template <bool>
struct implement_maybe_here
{};

template <>
struct implement_maybe_here<true>
{
    int maybe_here;
};

struct my_struct : implement_maybe_here<HAS_MAYBE_HERE>
{
    double always_here;
};
模板
结构实现在这里
{};
模板
结构实现在这里
{
int可能在这里;
};
结构我的结构:在这里实现
{
在这里加倍;
};
我不建议这样做,因为它很难维护,而且这里的
变量可能很难初始化(但无论采用何种方法,这都会是一团混乱)

请注意,您不能保证
implemente\u这里的
可能会占用零内存,但是许多编译器实现了这一点


对于第二种情况,使用
std::conditional
,正如@ForEveR建议的那样。

对于第二种情况,我通常更喜欢将黑客限制在一个位置的typedef:

#if SOME_CONSTANT > SOME_VALUE
    typedef uint8_t always_type;
#else
    typedef uint16_t always_type;
#endif
然后剩下的代码将始终使用
类型

struct MyStruct {
    // ...
    always_type always_here_but_different_size;
    // ...
};
如果要使用:

typedef std::conditional<(SOME_CONSTANT > VALUE), uint8_t, uint16_t>::type always_type;
typedef std::conditional VALUE),uint8\u t,uint16\u t>::始终键入;
这也很好——这里的重点不是关于获取所需类型所使用的语法,而是您通常希望为该类型创建一个名称,以便在需要时使用它

至于某物是否存在的情况,有点难说。通常,这样的事情与在构建时启用/禁用某些特性有关。如果是这样,则该类似乎既有与可启用/禁用的功能相关的职责,也有与其他功能相关的职责。这听起来可能违反了单一责任原则,而且可能没有很强的凝聚力。如果是这样的话,它可能表明一个问题在总体设计层面上得到了更好的解决,而不仅仅是您使用的语法


警告:我可能是从公认的最小证据中推断出了相当多的证据——可能比证据真正支持的要多。

加上联盟之外的另一个变量,它可以指示正在使用的字段。这很好,但它不是解决方案,因为这里没有定义-代码不会编译。所以,我认为我们根本无法取代ifdef。@ForEveR:当然。人们必须在某些时候使用一些预处理器,比如
#ifdef which#define has#u MAYBE#u HERE 1#否则…
,甚至像
#define has#u MAYBE(whichere)defined
这样的东西都可以工作。但是,这是以元编程方式将成员添加到类中的标准方法。是的,因此只有预处理器魔术可以替换struct中的#ifdef。因此,我认为这比使用一个“ifdef”的开销更大。@ForEveR:或者可以避免使用
#ifdef
,而使用
#define
来实现这一目的。我看到大部分注意力都集中在第二种情况,这很好,但实际上我对第一种情况更感兴趣。谢谢你的建议。