唉,你不能在预处理器中进行递归,但你可以制作一个“将宏应用于这个可变参数宏的所有参数”宏。
一个有用的想法是,当调用函数式宏时,() 可以是 参数 的一部分。这使您可以做一些时髦的事情。在你的具体例子中......
首先,一个宏告诉我们__VA_ARGS__ 包中有多少个参数:
#define NUM_ARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define NUM_ARGS(...) NUM_ARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
接下来,一个宏将给定的宏单独应用于__VA_ARGS__ 包的每个元素:
#define FOREACH(MACRO, ...) FOREACH_(NUM_ARGS(__VA_ARGS__), MACRO, __VA_ARGS__)
#define FOREACH_(N, M, ...) FOREACH__(N, M, __VA_ARGS__)
#define FOREACH__(N, M, ...) FOREACH_##N(M, __VA_ARGS__)
#define FOREACH_1(M, A) M(A)
#define FOREACH_2(M, A, ...) M(A) FOREACH_1(M, __VA_ARGS__)
#define FOREACH_3(M, A, ...) M(A) FOREACH_2(M, __VA_ARGS__)
#define FOREACH_4(M, A, ...) M(A) FOREACH_3(M, __VA_ARGS__)
#define FOREACH_5(M, A, ...) M(A) FOREACH_4(M, __VA_ARGS__)
#define FOREACH_6(M, A, ...) M(A) FOREACH_5(M, __VA_ARGS__)
#define FOREACH_7(M, A, ...) M(A) FOREACH_6(M, __VA_ARGS__)
#define FOREACH_8(M, A, ...) M(A) FOREACH_7(M, __VA_ARGS__)
// Extend in the obvious way for as many iterations as needed.
一个简单的“stringify one thing”宏(确保它的参数扩展):
#define STRINGIFY_(X) #X
#define STRINGIFY(X) STRINGIFY_(X)
现在让我们将所有部分放在一起,制作一个构建字符串数组的好例子:
#define STRINGIFY_ALL(...) FOREACH(STRINGIFY, __VA_ARGS__)
#define COMMA(X) X,
#define COMMA_STRINGIFY(X) COMMA(STRINGIFY(X))
#define STRING_LITERAL_ARRAY(...) const char* STUFF[ NUM_ARGS(__VA_ARGS__) ] = { FOREACH(COMMA_STRINGIFY, __VA_ARGS__) };
STRING_LITERAL_ARRAY(I, AM, A, POTATO);
// Will yield:
const char* STUFF[ 4 ] { "I", "AM", "A", "POTATO" };
希望您能看到如何编写不同的“类似 lambda”的宏来与 FOREACH 一起使用来完成各种令人兴奋的事情。