C++ 如何用宏删除圆括号?

C++ 如何用宏删除圆括号?,c++,macros,c-preprocessor,C++,Macros,C Preprocessor,宏参数中不允许使用逗号,因为它将被视为多个参数,并且预处理将出错。但是,我们可以将参数插入括号,让预处理器将其作为一个参数处理。是否有宏或其他技术可以删除括号 例如,如果我定义一个宏,如 #define MY_MACRO(a, b) ... 像这样使用它 MY_MACRO( A<int, double>, text ); MY_MACRO( (A<int, double>), text) MY_宏(A,文本); 这将是错误的。像这样使用它 MY_MACRO(

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

例如,如果我定义一个宏,如

#define MY_MACRO(a, b)   ...
像这样使用它

MY_MACRO( A<int, double>, text );
MY_MACRO( (A<int, double>), text)
MY_宏(A,文本);
这将是错误的。像这样使用它

MY_MACRO( A<int, double>, text );
MY_MACRO( (A<int, double>), text)
MY_宏((A),文本)
使用宏或技术删除括号就可以了。Boost仅为类型而非一般情况提供
Boost\u IDENTITY\u TYPE

#define ESC(...) __VA_ARGS__
然后

MY_宏(ESC(A),文本);

可能会做你想做的。

一个简单的方法就是使用可变宏:

#define MY_MACRO(a, b...)   ...
然后你可以像这样使用它:

MY_MACRO(text, A<int, double>)
MY_宏(文本,A)

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

此宏技巧类似于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;
}
#包括
#定义_参数(…)_参数__
#定义条带参数(X)X
#定义过程参数(X)带参数(_参数X)
int main()
{
printf(“没有宏%d%d%d%d%d%d\n”,(5,6,7,8,9,10));//这实际上是编译的,但它是错误的
printf(“使用宏%d%d%d%d%d%d\n”,传递_参数((5,6,7,8,9,10));//括号中的参数“pack”
返回0;
}
当然,您可以通过将PASS_PARAMETERS宏转换为可变宏并在多个参数包中进行传递来获得创造性。

仅可能删除括号: 如果需要去除一层括号,但只有在有括号要去除时,这组较长的宏才起作用:

#define DEPAREN(X) ESC(ISH X)
#define ISH(...) ISH __VA_ARGS__
#define ESC(...) ESC_(__VA_ARGS__)
#define ESC_(...) VAN ## __VA_ARGS__
#define VANISH
如果要对不同的数据类型集使用
MY\u宏
,则可能需要此选项:

#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_wu(wu VA_wuargs)
,这将展开内部

ISH(…)
变成
ISH\uu VA\u ARGS\uuuu
,从X中去掉一层括号。现在,不管X最初是否有括号,我们都有
ESC_uu(ISH X)

我们现在需要摆脱
ISH
。但是,因为我们已经定义了
ISH(…)
,所以不能将其定义为
#define ISH
。这就是为什么我们将它与另一个标记(
VAN
)连接起来,以获得
消失X


invision
被定义为
,因此我们最后只剩下
X
,没有括号。

一个解决方法-
typedef A IA;MY_宏(IA,文本)typedef比所有的预处理器黑客都要优雅。好简单!或者,ESC可以进入MY_宏,例如定义MY_宏(a,b)ESC a(b)
MY_宏((a),文本)-->
A(文本)(变量声明)这是一个很好的答案。需要了解的重要部分是,
\u Args
宏不会将
X
包装在
()
中。这样,它自然地连接和解析括号。