VC ++与GCC预处理器

时间:2014-07-22 18:14:39

标签: c++ gcc visual-c++ macros c-preprocessor

长话短说,gcc和vc ++预处理器具有相同输入的不同输出。如果传递给另一个宏,vc ++中的变量宏似乎不会进行“参数匹配”(如果它是正确的术语)。 例如:

#define MACRO(a, ...)        head:a, tail:MACRO_OTHER(__VA_ARGS__)
#define MACRO_OTHER(a, ...)  head:a, tail:__VA_ARGS__

使用

MACRO(1, 2, 3, 4, 5)

gcc输出:

head:1, tail:head:2, tail:3,4,5

vc ++输出:

head:1, tail:head:2,3,4,5, tail:

a中显然MACRO_OTHER2,3,4,5,其中包含空可变参数部分。 考虑到这一点,有没有办法创建一个vc ++替代以下的宏(这与gcc很好)

#define VA_TYPES_WITH_ARGS(...) __VA_TYPES_WITH_ARGS(VA_NUM_ARGS(__VA_ARGS__),##__VA_ARGS__)
#define __VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS(n,##__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS(n, ...) _VA_TYPES_WITH_ARGS_##n(__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS_0()
#define _VA_TYPES_WITH_ARGS_1(type     ) type _arg1
#define _VA_TYPES_WITH_ARGS_2(type, ...) type _arg2, _VA_TYPES_WITH_ARGS_1(__VA_ARGS__)
#define _VA_TYPES_WITH_ARGS_3(type, ...) type _arg3, _VA_TYPES_WITH_ARGS_2(__VA_ARGS__)
// etc

它基本上为每个参数附加_argK

示例:

VA_TYPES_WITH_ARGS(int, bool, float)

将扩展为

int _arg3, bool _arg2, float _arg1

非常感谢任何帮助。


相关预处理器问题:

Difference between gcc and Microsoft preprocessor

Unexpected Behaviour of GCC and VC++ Preprocessor

2 个答案:

答案 0 :(得分:3)

你可以通过使用Boost以合理的交叉编译方式(并接受更多参数而无需额外的工作来启动)来实现这一点,我可以告诉你,花费这么多时间查看标题,有很多变通方法适用于以下问题:

#define VA_TYPES_WITH_ARGS(...)   \
    BOOST_PP_ENUM(                \
        BOOST_PP_VARIADIC_SIZE(__VA_ARGS__),    \
        VA_TYPES_WITH_ARGS_MACRO,               \
        BOOST_PP_VARIADIC_TO_TUPLE(__VA_ARGS__) \
    )

#define VA_TYPES_WITH_ARGS_MACRO(z, n, data)       \
    BOOST_PP_TUPLE_ELEM(n, data) BOOST_PP_CAT(     \
        _arg,                                      \
        BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(data), n) \
    )                                              

VA_TYPES_WITH_ARGS(int, bool, float) //int _arg3 , bool _arg2 , float _arg1

第一个宏在可变参数上枚举(ENUM),为每个参数调用第二个并添加加入逗号。它从可变参数数据形成一个元组,以提供给第二个宏。

第二个形成元素(TUPLE_ELEM)后跟_arg连接(CAT)与size - nSUB),其中size是可变参数数据中的元素数(作为元组赋予宏)(TUPLE_SIZE)。

See it work.

答案 1 :(得分:3)

适用于VC ++的独立方法是:GCC,它是:

#define EXPAND(...) __VA_ARGS__
#define LPAREN (
#define RPAREN )

现在,不要使用像x(__VA_ARGS__)这样的宏,而是像这样使用它:EXPAND(x LPAREN __VA_ARGS__ RPAREN)

这会强制VC ++预处理器比通常更晚扫描参数。

您应该能够将两个表单组合在一起,将特定于编译器的位放在一个位置。

请注意,不能是标准的C ++答案:您依赖x()作为没有参数的宏调用。这不是预处理器在标准C ++中的工作方式:如果x是可变参数宏,x()将使用单个参数调用宏,并且该单个参数为空。此外,您依赖于能够省略可变参数:标准C ++也不允许这样做。如果宏定义为#define FOO(x,...),则将其作为FOO(1)调用无效。由于不存在标准方法,所以对于您而言,各种方法必然是特定于编译器的,这对您来说不是一个问题。