长话短说,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_OTHER
为2,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
非常感谢任何帮助。
相关预处理器问题:
答案 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 - n
(SUB
),其中size
是可变参数数据中的元素数(作为元组赋予宏)(TUPLE_SIZE
)。
答案 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)
调用无效。由于不存在标准方法,所以对于您而言,各种方法必然是特定于编译器的,这对您来说不是一个问题。