C预处理程序:迭代地将宏扩展为逗号分隔的列表 [英] C-preprocessor: iteratively expand macro to comma-separated list
问题描述
在帖子 C预处理程序递归宏中使用Paul Fultz II的解决方案,想扩展无限数量的带括号的宏参数,例如
Using Paul Fultz II's solution in the post C-preprocessor recursive macro, I'd like to expand an unlimited number of parenthesized macro arguments, e.g.
#define MY_CHAIN (alpha) (beta) (gamma)
进入逗号分隔的列表,该列表可以传递给可变参数宏,例如
into a comma-separated list which can be passed to a variadic macro, e.g.
CHAIN_COMMA(MY_CHAIN) // alpha, beta, gamma
我可以展开成大括号[alpha] [beta] [gamma]
,并用除逗号(在下面的示例中为alpha :: beta :: gamma
)之外的所有内容定界列表.
I'm able to expand into braces [alpha] [beta] [gamma]
and delimit the list with everything I've tried except a comma, alpha :: beta :: gamma
in the example below.
这是我完整的(编译)代码:
Here is my full (compiling) code:
#include <iostream>
using namespace std;
// unrelated macro utilities
#define SEE(expression) cout << #expression ": " << STR(expression) << endl;
#define CMD(function, ...) function(__VA_ARGS__)
#define STR(s) CMD(STR_, s)
#define STR_(s) #s
// concatenation
#define CAT(x, y) CAT_(x, y)
#define CAT_(x,y) x ## y // error from CHAIN_COMMA: passed 4 arguments
// surround each chain element with square brackets []
#define CHAIN_BRACE(chain) CAT(CHAIN_BRACE_1 chain, _END)
#define CHAIN_BRACE_1(x) [x] CHAIN_BRACE_2
#define CHAIN_BRACE_2(x) [x] CHAIN_BRACE_1
#define CHAIN_BRACE_1_END
#define CHAIN_BRACE_2_END
// separate each chain element with the scope operator ::
#define CHAIN_SCOPE(chain) CAT(CHAIN_SCOPE_0 chain, _END)
#define CHAIN_SCOPE_0(x) x CHAIN_SCOPE_1
#define CHAIN_SCOPE_1(x) :: x CHAIN_SCOPE_2
#define CHAIN_SCOPE_2(x) :: x CHAIN_SCOPE_1
#define CHAIN_SCOPE_0_END
#define CHAIN_SCOPE_1_END
#define CHAIN_SCOPE_2_END
// trouble here: can't separate chain elements with commas
#define CHAIN_COMMA(chain) CAT(CHAIN_COMMA_0 chain, _END) // error
#define CHAIN_COMMA_0(x) x CHAIN_COMMA_1
#define CHAIN_COMMA_1(x) , x CHAIN_COMMA_2
#define CHAIN_COMMA_2(x) , x CHAIN_COMMA_1
#define CHAIN_COMMA_0_END
#define CHAIN_COMMA_1_END
#define CHAIN_COMMA_2_END
// define a custom chain and save various forms of it
#define MY_CHAIN (alpha) (beta) (gamma)
#define MY_BRACES CHAIN_BRACE(MY_CHAIN) // [alpha] [beta] [gamma]
#define MY_SCOPES CHAIN_SCOPE(MY_CHAIN) // alpha :: beta :: gamma
#define MY_COMMAS CHAIN_COMMA(MY_CHAIN) // alpha , beta , gamma
int main() {
SEE(MY_CHAIN);
SEE(MY_BRACES);
SEE(MY_SCOPES);
// SEE(MY_COMMAS); // error: macro "CAT_" passed 4 arguments, but takes just 2
return 0;
}
这将输出:
MY_CHAIN: (alpha) (beta) (gamma)
MY_BRACES: [alpha] [beta] [gamma]
MY_SCOPES: alpha :: beta :: gamma
我尝试用括号将逗号分隔的列表括起来,但是CAT不会将)
附加到_END
.有什么聪明的想法可以扩展到alpha, beta, gamma
吗?
I tried parenthesizing the comma-separated list but CAT won't append )
to _END
. Any clever ideas to expand into alpha, beta, gamma
?
推荐答案
由于逗号对于您的输出既重要,又是一个语法元素,因此您需要为输出添加一个替换逗号.
As the comma is both important to your output and is a syntactic element you need to make a substitute comma for outputting.
#define COMMA() ,
我们还将需要一些延迟函数,以便不会立即评估COMMA
.
We will also need some deferring functions so that COMMA
isn't evaluated immediately.
#define EMPTY()
#define DEFER(id) id EMPTY()
现在我们可以将您的两个宏重新定义为
Now we can redefine your two macros into
#define CHAIN_COMMA_1(x) DEFER(COMMA)() x CHAIN_COMMA_2
#define CHAIN_COMMA_2(x) DEFER(COMMA)() x CHAIN_COMMA_1
但是,您的SEE
宏也不喜欢所放置的逗号,因此必须传递许多参数也会出错.
However your SEE
macro also doesn't like the commas that are placed and so will error for having to many parameters passed.
You can see that this is performing correctly by looking at the output of the preprocessor with the -E
option.
这篇关于C预处理程序:迭代地将宏扩展为逗号分隔的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!