我正在尝试为C ++中的新std::optional<T>
创建匹配机制。我写了以下宏:
#define EXPAND(x) x
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(EXPAND(x), EXPAND(y))
#define if_opt__(xalt, bval, x, y) \
auto xalt = y; \
bool bval = true; \
if (xalt.has_value()) \
for (auto x = xalt.value(); bval; bval = false)
#define if_opt_(xalt, x, y) if_opt__(xalt, CAT(xalt, _b), x, y)
#define if_opt(x, y) if_opt_(CAT(x, __LINE__), x, y)
我已经为它创建了以下示例程序:
std::optional<int> get(int a) {
if (a < 0) {
return {};
}
return a;
}
int main(void) {
if_opt(a, get(0)) {
std::cout << "optional matched!" << std::endl;
}
return 0;
}
然而,当我尝试编译程序时,我会遇到类似“重新定义”的错误;不同的基本类型&#39;。然后我将它预处理到一个文件,复制结果,它编译和工作就好了。该宏评估为:
auto a24 = get(0);
bool a24_b = true;
if (a24.has_value())
for (auto a = a24.value(); a24_b; a24_b = false) {
std::cout << "optional matched!" << std::endl;
}
为什么不使用宏本身编译?我正在使用MSVC。
答案 0 :(得分:2)
应更正CAT
宏执行额外扩展的方式:
//#define EXPAND(x) x // not needed
#define CAT_(x, y) x##y
#define CAT(x, y) CAT_(x, y)
当它在某个时刻被展开时,会产生表达式EXPAND(x)##EXPAND(y)
,这会打破进一步的扩展,因为##只能使用普通标记,甚至不会尝试展开EXPAND
。
为什么它在预处理到文件时有效?可能是因为VS有非常花哨(和不符合)的处理方式。即使在对文件进行预处理时,Gcc也会为您提供更好的诊断。