use*_*020 13 c++ macros c-preprocessor
宏参数中不允许使用逗号,因为它将被视为多个参数,并且预处理将是错误的.但是,我们可以将参数括起来让预处理器将其视为一个参数.是否有宏或其他技术可以删除括号括起来?
例如,如果我定义一个宏
#define MY_MACRO(a, b) ...
Run Code Online (Sandbox Code Playgroud)
并使用它
MY_MACRO( A<int, double>, text );
Run Code Online (Sandbox Code Playgroud)
会错的.用它就像
MY_MACRO( (A<int, double>), text)
Run Code Online (Sandbox Code Playgroud)
用宏或技术来删除括号将是好的.Boost BOOST_IDENTITY_TYPE仅为类型提供宏,但不提供一般情况
Yak*_*ont 17
#define ESC(...) __VA_ARGS__
Run Code Online (Sandbox Code Playgroud)
然后
MY_MACRO( ESC(A<int, double>), text );
Run Code Online (Sandbox Code Playgroud)
可能会做你想要的.
小智 14
如果您需要删除一层括号,但仅当有括号要删除时,这组较长的宏就可以解决问题:
#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
Run Code Online (Sandbox Code Playgroud)
MY_MACRO如果您想使用不同的数据类型集,则可能需要这样做:
#define MY_MACRO(a, b) DEPAREN(a), b
MY_MACRO( ({x, y, z}), text )
//> {x,y,z}, text
MY_MACRO( singlearg, text )
//> singlearg, text
Run Code Online (Sandbox Code Playgroud)
我们从 开始DEPAREN(X) ESC(ISH X)。如果 X 有括号,我们得到ESC(ISH(X))。如果 X 没有括号,我们得到ESC(ISH X)。
然后我们扩展ESC(...)到ESC_(__VA_ARGS__),从而扩展了内部。
ISH(...)变成ISH __VA_ARGS__,它从 X 中去掉一层括号。现在,无论 X 最初是否有括号,我们有ESC_(ISH X)。
我们现在需要摆脱ISH. 然而,因为我们已经定义了ISH(...),所以我们不能将它也定义为#define ISH 。这就是为什么我们将它与另一个标记 ( VAN) 连接起来得到VANISH X。
VANISH被定义为 ,所以我们最终剩下X, 没有括号。
小智 7
这个宏技巧类似于Yakk的解决方案,但不需要显式传入另一个宏作为参数.
#include <stdio.h>
#define _Args(...) __VA_ARGS__
#define STRIP_PARENS(X) X
#define PASS_PARAMETERS(X) STRIP_PARENS( _Args X )
int main()
{
printf("without macro %d %d %d %d %d %d\n", (5,6,7,8,9,10) ); // This actually compiles, but it's WRONG
printf("with macro %d %d %d %d %d %d\n", PASS_PARAMETERS((5,6,7,8,9,10)) ); //Parameter "pack" enclosed in parenthesis
return 0;
}
Run Code Online (Sandbox Code Playgroud)
当然,您可以通过将PASS_PARAMETERS宏转换为可变参数宏并传入多个参数包来获得创意.