【问题标题】:How to remove the enclosing parentheses with macro?如何用宏删除括号?
【发布时间】:2014-06-30 01:17:19
【问题描述】:

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

例如,如果我定义一个宏

#define MY_MACRO(a, b)   ...

并像使用它

MY_MACRO( A<int, double>, text );

会错的。像这样使用它

MY_MACRO( (A<int, double>), text)

使用宏或技术来删除括号就可以了。 Boost 只为类型提供了BOOST_IDENTITY_TYPE 宏,而不是一般情况

【问题讨论】:

  • 解决方法 - typedef A&lt;int, double&gt; IA; MY_MACRO(IA, text);
  • typedef 比所有预处理器 hack 恕我直言更优雅

标签: c++ macros c-preprocessor


【解决方案1】:
#define ESC(...) __VA_ARGS__

然后

MY_MACRO( ESC(A<int, double>), text );

可以为所欲为。

【讨论】:

  • 哇。好简单!
  • 或者 ESC 可以进入 MY_MACRO,例如#define MY_MACRO(a,b) ESC a (b) MY_MACRO( (A&lt;int,double&gt;), text ); --> A&lt;int,double&gt; (text);(变量声明)
【解决方案2】:

这个宏技巧类似于 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 宏制作成可变参数宏并传入多个参数包来获得创意。

【讨论】:

  • 这是一个很好的答案。要理解的重要部分是_Args 宏确实X 包装在() 中。这样,它自然地连接和解析括号。
【解决方案3】:

只能去掉括号:

如果你需要去掉一层括号,但只有当有括号要去掉时,这组更长的宏可以解决问题:

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

【讨论】:

  • 真是天才!
【解决方案4】:

一个简单的技巧是使用可变参数宏:

#define MY_MACRO(a, b...)   ...

然后你可以像这样使用它:

MY_MACRO(text, A<int, double>)

第二个参数中的逗号仍然被解释为参数分隔符(意味着宏实际上是用三个参数调用的),但它在宏内部展开,使得行为相同。然而,可变参数必须在宏中的最后。

【讨论】:

    猜你喜欢
    • 2017-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 2021-04-11
    相关资源
    最近更新 更多