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

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)

可能会做你想要的.

  • 或者ESC可以进入MY_MACRO,例如`#define MY_MACRO(a,b) ESC a (b)` `MY_MACRO( (A&lt;int,double&gt;), text );` --&gt; `A&lt;int,double&gt; (文本);` (变量声明) (3认同)

小智 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, 没有括号。

  • 这真是天才啊! (2认同)

小智 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宏转换为可变参数宏并传入多个参数包来获得创意.