在某些情况下,您需要(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()
将多个模板参数传递给一个fixture)。 / p>
答案 0 :(得分:4)
So I came to the following pure-preprocessor solution that will strip parentheses only when they are present. Seems to work in vc++, g++ and clang++ and probably can be modified to deal with several levels of parentheses.
#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
答案 1 :(得分:-1)
不是很好的解决方案,但如果有问题的结构可以修改,并且只支持一个级别的括号,这似乎有效:
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