如何用宏删除括号括起来?

时间:2014-06-30 01:17:19

标签: c++ macros c-preprocessor

宏参数中不允许使用逗号,因为它将被视为多个参数,并且预处理将是错误的。但是,我们可以将参数括起来让预处理器将其视为一个参数。是否有宏或其他技术可以删除括号?

例如,如果我定义一个像

这样的宏
#define MY_MACRO(a, b)   ...

并像

一样使用它
MY_MACRO( A<int, double>, text );

会错的。像

一样使用它
MY_MACRO( (A<int, double>), text)

使用宏或技术删除括号将没问题。 Boost仅为类型提供BOOST_IDENTITY_TYPE宏,但不提供一般情况

4 个答案:

答案 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,没有括号。