C预处理程序:迭代地将宏扩展为逗号分隔的列表 [英] C-preprocessor: iteratively expand macro to comma-separated list

查看:124
本文介绍了C预处理程序:迭代地将宏扩展为逗号分隔的列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在帖子 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆