我必须生成一个仅在某些条件下包含某些字段的数据结构。这通常会转换为类似以下内容的
struct MyStruct {
int alwaysHere;
#ifdef WHATEVER
bool mightBeHere;
#endif
char somethingElse;
#if SOME_CONSTANT > SOME_VALUE
uint8_t alywasHereButDifferentSize;
#else
uint16_t alywasHereButDifferentSize;
#endif
...
};
从我的观点来看,这看起来很难看,而且难以理解。 甚至没有谈论处理这些字段的代码,通常是在 ifdef也是。
我正在寻找一种优雅的方法来实现相同的结果,而不会增加任何开销,但代码很多 更具可读性。模板专业化似乎有点过分,但在我看来 成为唯一的选择。
C ++ 11是否会添加任何内容来处理这种情况?
任何建议都将不胜感激。
答案 0 :(得分:5)
对于第二种情况,我通常更喜欢将hackery限制在一个地方的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;
那也没关系 - 这里的重点不是你用来获得你想要的类型的语法,而是你通常想为这个类型创建一个名字,这样你就可以在需要时使用它。
至于某事物是否存在的情况,很难说是 little 。通常,这样的事情将涉及在构建时启用/禁用某些功能。如果是这样,那么该类似乎具有与可以启用/禁用的功能相关的职责,以及与其他功能相关的职责。这听起来似乎违反了单一责任原则,可能不是很有凝聚力。如果是这种情况,它可能表明在整体设计层面上更好地解决的问题,而不仅仅是您使用的语法。
警告:我可能从公认的最小证据中推断出相当多的证据 - 可能超过证据确实支持的证据。答案 1 :(得分:4)
第二种情况可以替换为
std::conditional<(SOME_CONSTANT > SOME_VALUE), uint8_t, uint16_t>::type
alywasHereButDifferentSize;
首先我认为没有。
答案 2 :(得分:1)
我已经看到这样做了一个工会(http://www.cplusplus.com/doc/tutorial/other_data_types/),但我不确定具体细节,因为我自己从未实现过。你将拥有:
而不是第二块宏观困境union {
uint8_t alywasHereButDifferentSize;
uint16_t alywasHereButDifferentSize;
}
并且在引用时,你会得到一个if引用一个或另一个变量。
或者,您可以创建一个void *指针,在运行时将其初始化为任一类型的变量。
答案 3 :(得分: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>
将占用零内存,但是许多编译器会实现此“empty base optimization”。
使用std::conditional
作为第二个,正如@ForEveR建议的那样。