2

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

struct MyStruct {
    int     alwaysHere;

#ifdef WHATEVER
    bool    mightBeHere;
#endif

    char    somethingElse;

#if SOME_CONSTANT > SOME_VALUE
    uint8_t alywasHereButDifferentSize;
#else
    uint16_t alywasHereButDifferentSize;
#endif
...
};

从我的角度来看,这很容易看起来很难看,而且不可读。甚至不用谈论处理这些字段的代码,通常也是在 ifdefs 下。

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

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

任何建议将不胜感激。

4

4 回答 4

5

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

#if SOME_CONSTANT > SOME_VALUE
    typedef uint8_t always_type;
#else
    typedef uint16_t always_type;
#endif

然后您的其余代码将always_type始终使用:

struct MyStruct {
    // ...
    always_type always_here_but_different_size;
    // ...
};

如果你想使用:

typedef std::conditional<(SOME_CONSTANT > VALUE), uint8_t, uint16_t>::type always_type;

这也很好——这里的重点不在于您用于获取所需类型的语法,而是您通常希望为该类型创建一个名称以便可以在需要时使用它的事实。

至于有没有东西的情况,就有点难说了。通常,这样的事情将与在构建时启用/禁用某些功能有关。如果是这样,则该类似乎具有与可以启用/禁用的功能以及其他内容相关的职责。这听起来可能违反了单一责任原则,并且可能不是很有凝聚力。如果是这种情况,它可能表明一个问题在整体设计级别上得到了更好的解决,而不仅仅是您使用的语法。

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

于 2012-07-07T16:36:14.057 回答
4

第二种情况可以替换为

std::conditional<(SOME_CONSTANT > SOME_VALUE), uint8_t, uint16_t>::type
alywasHereButDifferentSize;

首先我认为没有。

于 2012-07-07T15:22:08.693 回答
1

我已经通过联合(http://www.cplusplus.com/doc/tutorial/other_data_types/)看到了这一点,但我不确定具体细节,因为我自己从未实现过。而不是第二个宏黑客,您将拥有:

union {
  uint8_t alywasHereButDifferentSize;
  uint16_t alywasHereButDifferentSize;
}

并且在引用时,您将有一个 if 引用一个或另一个变量。

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

于 2012-07-07T15:22:00.287 回答
0

为了第一:

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;
};

我不建议以任何方式这样做,因为它难以维护并且maybe_here变量难以初始化(但使用任何方法,无论如何这都会是一团糟)。

请注意,您不能保证implement_maybe_here<false>会占用零内存,但是许多编译器实现了这种“空基优化”。

正如@ForEveRstd::conditional建议的那样,用于第二个。

于 2012-07-07T16:23:30.380 回答