C++ #宏调用中的ifdef可用于gcc,但不能用于msvc

C++ #宏调用中的ifdef可用于gcc,但不能用于msvc,c++,visual-c++,gcc,macros,variadic-macros,C++,Visual C++,Gcc,Macros,Variadic Macros,我有一个宏类型列表,它接受可变参数。我想要像这样的东西 typedef TYPELIST(A ,B ,C ,D #ifdef BLA_ ,E #endif ,F) 这在gcc中非常有效。但是,当我尝试用MSVC编译它时,它会将ifdef和endif解析为宏参数。我知道一种方法是将宏调用放入ifdef中。然而,如果我有一个巨大的列表,并且

我有一个宏类型列表,它接受可变参数。我想要像这样的东西

typedef TYPELIST(A
                ,B
                ,C
                ,D
#ifdef BLA_
                ,E
#endif
                ,F)
这在gcc中非常有效。但是,当我尝试用MSVC编译它时,它会将ifdef和endif解析为宏参数。我知道一种方法是将宏调用放入ifdef中。然而,如果我有一个巨大的列表,并且如果我想根据定义的不同宏包含不同的类,那么它将变得单调乏味。这在gcc中工作而不在MSVC中工作,有什么特别的原因吗?

在宏中使用#ifdef是不合法的。我有点惊讶gcc允许这样做。恐怕你必须在整个定义中加入#ifdef,即

#ifdef BLA_
    typedef TYPELIST(a,b,c,d,e,f)
#else
    typedef TYPELIST(a,b,c,d,f)
#endif
根据标准(§16.3.4/3),“产生的 宏替换的预处理令牌序列未按以下方式处理 一个预处理指令,即使它类似于一个“[…]”。如果 g++在这里处理
#ifdef/#endif
,这是 编译器(至少如果您要求符合标准,
e、 g.带有
-std=…
-std=c++03强制标准一致性,但它仍然没有抱怨。实际上,这不是一个错误,只是一个错误。16.3/11(谈论类似宏的函数的参数):“如果参数列表中有一系列预处理标记,否则将用作预处理指令,则行为未定义。”啊,是的。“扩展到预处理器指令”和参数列表中的预处理标记之间存在差异。因此,就标准而言,这不是一个错误;对于他们如何处理未定义的行为,这只是一个糟糕的选择(虽然不是一个选择,它可能与他们如何标记有关)。从形式不良的意义上讲,这并不违法,它只是有未定义的行为。所以gcc可以接受它。