C 预处理器:将宏迭代扩展为逗号分隔列表
C-preprocessor: iteratively expand macro to comma-separated list
在 post C-preprocessor recursive macro 中使用 Paul Fultz II 的解决方案,我想扩展无限数量的带括号的宏参数,例如
#define MY_CHAIN (alpha) (beta) (gamma)
进入一个逗号分隔的列表,可以传递给可变参数宏,例如
CHAIN_COMMA(MY_CHAIN) // alpha, beta, gamma
我能够扩展成大括号 [alpha] [beta] [gamma]
并用我尝试过的所有内容分隔列表,逗号除外,在下面的示例中 alpha :: beta :: gamma
。
这是我的完整(编译)代码:
#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
?
由于逗号对你的输出很重要,也是一个句法元素,所以你需要制作一个替代逗号来输出。
#define COMMA() ,
我们还需要一些延迟函数,这样 COMMA
就不会立即求值。
#define EMPTY()
#define DEFER(id) id EMPTY()
现在我们可以将您的两个宏重新定义为
#define CHAIN_COMMA_1(x) DEFER(COMMA)() x CHAIN_COMMA_2
#define CHAIN_COMMA_2(x) DEFER(COMMA)() x CHAIN_COMMA_1
但是,您的 SEE
宏也不喜欢放置的逗号,因此会因传递过多参数而出错。
您可以通过 looking at the output of the preprocessor 和 -E
选项看到宏正在正确执行。
在 post C-preprocessor recursive macro 中使用 Paul Fultz II 的解决方案,我想扩展无限数量的带括号的宏参数,例如
#define MY_CHAIN (alpha) (beta) (gamma)
进入一个逗号分隔的列表,可以传递给可变参数宏,例如
CHAIN_COMMA(MY_CHAIN) // alpha, beta, gamma
我能够扩展成大括号 [alpha] [beta] [gamma]
并用我尝试过的所有内容分隔列表,逗号除外,在下面的示例中 alpha :: beta :: gamma
。
这是我的完整(编译)代码:
#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
?
由于逗号对你的输出很重要,也是一个句法元素,所以你需要制作一个替代逗号来输出。
#define COMMA() ,
我们还需要一些延迟函数,这样 COMMA
就不会立即求值。
#define EMPTY()
#define DEFER(id) id EMPTY()
现在我们可以将您的两个宏重新定义为
#define CHAIN_COMMA_1(x) DEFER(COMMA)() x CHAIN_COMMA_2
#define CHAIN_COMMA_2(x) DEFER(COMMA)() x CHAIN_COMMA_1
但是,您的 SEE
宏也不喜欢放置的逗号,因此会因传递过多参数而出错。
您可以通过 looking at the output of the preprocessor 和 -E
选项看到宏正在正确执行。