我正在尝试创建一个宏,它将迭代定义的术语列表,并为每个调用另一个宏,可能还有其他参数列表。这是我得到的:
#define ITERATE_OVER_TERMS(MACRO, ...) \
MACRO(Term1, __VA_ARGS__) \
MACRO(Term2, __VA_ARGS__) \
MACRO(Term3, __VA_ARGS__) \
... and so on
但是,当我尝试在Visual Studio 2015中使用它时,我收到错误
warning C4003: not enough actual parameters for macro 'BODY'
其中BODY
是作为MACRO
参数传递的宏的名称。虽然技术上是一个警告,但它表明扩展出了问题。
为了缩小错误范围,我将我的示例简化为以下内容:
#include <iostream>
#define ITERATE(MACRO, ...) \
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__)
#define BODY(IterationArg, Arg1, Arg2) \
std::cout << IterationArg << Arg1 << Arg2 << std::endl;
int main() {
ITERATE(BODY, 8, 9)
return 0;
}
它给出了如上所示的错误,而我希望它能够成功编译并生成输出
189
289
似乎用g ++编译,但不是Visual Studio。 我错过了什么?是否有一些解决方法可以解决这个问题?
答案 0 :(得分:2)
问题是Visual Studio在传递到后续宏之后扩展__VA_ARGS__
,而不是之前。这也引起了过去的问题,例如在这里 -
Why does this variadic argument count macro fail with VC++?
在您的情况下,请考虑对代码进行简单更改:
#include <iostream>
#define ITERATE(MACRO, ...) \
MACRO(1, __VA_ARGS__) MACRO(2, __VA_ARGS__)
#define BODY(IterationArg, Arg1, Arg2) \
std::cout << #Arg1 << std::endl;
int main() {
ITERATE(BODY, 8, 9)
return 0;
}
参数#Arg1
被字符串化,在输出中显示其内容:
8, 9
8, 9
不是我们的预期,是吗?
解决方案与链接问题中的解决方案相同:通过虚拟EXPAND
宏强制扩展:
#define EXPAND(x) x
#define ITERATE(MACRO, ...) \
EXPAND(MACRO(1, __VA_ARGS__)) EXPAND(MACRO(2, __VA_ARGS__))
这样可以在VS和gcc中获得所需的结果。