宏调用中的 #ifdef 适用于 gcc,但不适用于 msvc
Posted
技术标签:
【中文标题】宏调用中的 #ifdef 适用于 gcc,但不适用于 msvc【英文标题】:#ifdef inside a macro call works with gcc but not with msvc 【发布时间】:2013-10-01 08:27:53 【问题描述】:我有一个宏 TYPELIST,它接受可变参数。我想要类似的东西
typedef TYPELIST(A
,B
,C
,D
#ifdef BLA_
,E
#endif
,F)
这与 gcc 完美配合。但是,当我尝试使用 MSVC 编译它时,它会将 ifdef 和 endif 解析为宏参数。我知道一种方法是将宏调用放在 ifdef 中。但是,如果我有一个巨大的列表,并且如果我想根据定义的不同宏包含不同的类,那将变得乏味。这有什么特殊原因可以在 gcc 中而不是在 MSVC 中使用吗?
【问题讨论】:
是的,将预处理器指令放在宏调用中是不合法的 C++。如果您尝试这样做,编译器可以做他们喜欢的事情。如您所见,g++ 和 MSVC 做不同的事情。 @john,你的评论不应该是一个更好的答案吗? GCC 和 MSVC 的哪个版本? @AdriC.S.这是对他问题的回答,但不是对他问题的真正回答。也许其他人可以提出一个可行的解决方案。 gcc-4.7 和 cl-16.00.30319.01 【参考方案1】:在宏中使用#ifdef 是不合法的。我有点惊讶 gcc 允许这样做。恐怕您必须将#ifdef 放在整个定义中,即
#ifdef BLA_
typedef TYPELIST(a,b,c,d,e,f)
#else
typedef TYPELIST(a,b,c,d,f)
#endif
【讨论】:
在格式错误的意义上它不是非法的,它只是有未定义的行为。所以 gcc 可以接受就好了。【参考方案2】:根据标准(§16.3.4/3),“结果完全
宏替换的预处理标记序列不被处理为
一个预处理指令,即使它类似于一个,[...]"。如果
g++ 在这里处理#ifdef/#endif
,这是一个错误
编译器(至少如果您要求符合标准,
例如与-std=...
)。
【讨论】:
但它适用于 g++ 和 clang++。我还尝试使用-std=c++03
强制标准一致性,但它仍然没有抱怨。
其实不是错误,只是UB。 16.3/11(谈论类函数宏的参数):“如果在参数列表中存在预处理标记序列,否则它们将充当预处理指令,则行为未定义。”
啊,是的。 “扩展为预处理器指令”和预处理参数列表中的标记之间存在差异。因此,就标准而言,这不是错误;只是他们如何处理未定义行为的一个糟糕的选择(尽管它可能与他们如何标记化有关)。以上是关于宏调用中的 #ifdef 适用于 gcc,但不适用于 msvc的主要内容,如果未能解决你的问题,请参考以下文章
在 GCC 中将 0 参数传递给可变参数宏失败,但仅在 C++ 中?