【问题标题】:Dealing with extra parentheses in macros in MSVC在 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 不。没有这样的运气。

标签: c++ visual-c++ macros


【解决方案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() 却没有?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-13
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 1970-01-01
  • 1970-01-01
  • 2011-04-03
相关资源
最近更新 更多