宏参数中不允许使用逗号,因为它将被视为多个参数,并且预处理将是错误的。但是,我们可以将参数括起来让预处理器将其视为一个参数。是否有宏或其他技术可以删除括号?
例如,如果我定义一个像
这样的宏#define MY_MACRO(a, b) ...
并像
一样使用它MY_MACRO( A<int, double>, text );
会错的。像
一样使用它MY_MACRO( (A<int, double>), text)
使用宏或技术删除括号将没问题。 Boost仅为类型提供BOOST_IDENTITY_TYPE
宏,但不提供一般情况
答案 0 :(得分:17)
#define ESC(...) __VA_ARGS__
然后
MY_MACRO( ESC(A<int, double>), text );
可能会做你想要的。
答案 1 :(得分:6)
这个宏技巧类似于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;
}
当然,您可以通过将PASS_PARAMETERS宏转换为可变参数宏并传入多个参数包来获得创意。
答案 2 :(得分:1)
一个简单的黑客可能是使用可变参数宏:
#define MY_MACRO(a, b...) ...
然后你就可以使用它:
MY_MACRO(text, A<int, double>)
第二个参数中的逗号仍然被解释为参数分隔符(意味着宏实际上是用三个参数调用的),但它在宏内扩展,使行为相同。然而,可变参数必须在宏中最后。
答案 3 :(得分:1)
如果您需要去除括号中的一层,但仅当有括号要去除时,这组较长的宏才有用:
#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
如果要将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
我们从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
,没有括号。