在 MSVC 中处理宏中的额外括号

Posted

技术标签:

【中文标题】在 MSVC 中处理宏中的额外括号【英文标题】:Dealing with extra parentheses in macros in MSVC 【发布时间】:2018-04-19 19:28:15 【问题描述】:

在某些情况下,您需要 (a) 有一个宏,该宏 (b) 在 (c) 语言不允许括号的情况下将其参数之一括起来。

简单示例:

#define MAKE_STRUCT(name, base) struct name : base  

struct X  ;
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // error

这是一个错误,因为我们需要一个类型名称并且我们得到(。 ecatmur 利用语言的其他部分确实允许额外的括号集这一事实,为此提供了一个巧妙的解决方法:

template<typename T> struct argument_type;
template<typename T, typename U> struct argument_type<T(U)>  typedef U type; ;

#define MAKE_STRUCT(name, base) struct name : argument_type<void(base)>::type  

struct X  ;
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok

这可以在 gcc 和 clang 上编译,但不能在 MSVC 上编译。是否存在允许使用括号的特定于 MSVC 的技巧或适用于所有三个编译器的不同技巧?

这个可能带括号的类型通过几个宏传递 - 所以我不确定其他答案是否适用(这里的上下文是尝试使用 Catch2 的 TEST_CASE_METHOD() 将多个模板参数传递给夹具)。

【问题讨论】:

@VTT 不。没有这样的运气。 【参考方案1】:

因此,我想到了以下纯预处理器解决方案,该解决方案仅在括号存在时才去除括号。似乎可以在 vc++、g++ 和 clang++ 中工作,并且可能可以修改以处理多个级别的括号。

#define MAKE_STRUCT(name, base) struct name: EXPAND1(DEF base) 
#define EXPAND1(param) EXPAND2(param)
#define EXPAND2(param) NO## param
#define DEF(param) DEF param
#define NODEF

struct X  ;
MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok

online compiler

【讨论】:

在我的情况下,X 中确实有一个逗号,但将DEFEXPAND2 改为... 是一个微不足道的改变。太好了,谢谢。预处理器对我来说基本上还是很神奇的。【参考方案2】:

不是很好的解决方案,但如果可以修改有问题的结构,并且只支持一级括号,这似乎可行:

struct tag ;

#define MAKE_STRUCT(name, base) struct name : \
  decltype(base(tag))  ;

struct X 
     X(tag );
     X() = default;
;

MAKE_STRUCT(Y, X);   // ok
MAKE_STRUCT(Z, (X)); // ok

【讨论】:

不幸的是,没有。但我很着迷这是有效的,而 base() 却没有?

以上是关于在 MSVC 中处理宏中的额外括号的主要内容,如果未能解决你的问题,请参考以下文章

您是不是使用花括号进行额外的范围界定? [关闭]

什么时候可以省略宏中参数周围的括号?

运行时滚动视图中的额外空间(插图)

Python 函数正在创建一个额外的元组

Horizo​​ntalPager 中的额外填充

在 MSVC 2010 命令行中强制 32 位编译