我想写一个通用的lambda作为变体的访问者。此变体的成员包含constexpr成员值,我想在访问者中使用它。例如:
#include <variant>
template<int r>
struct S {
constexpr static int this_r = r;
};
int f(std::variant<S<0>, S<1>, S<2> > v) {
return std::visit([](auto const& arg) {
if constexpr(arg.this_r == 0) { return 42; }
else { return arg.this_r; }
}, v);
}
int g() {
std::variant<S<0>, S<1>, S<2> > x = S<2>();
return f(x);
}
GCC很高兴从version 7.1开始编译此代码。另一方面,Clang抱怨arg.this_r == 0
的{{1}}参数不是常量,可以追溯到version 4.0.0,但是它仍然存在于current trunk中。>
谁在这里,我该如何避免这个问题(假设一个简单的if constexpr
不能切掉,因为两个分支之一无法实例化)?
附录:将if
作为值而不是常量左值引用Clang is happy进行传递,但不幸的是,这不是我的选择。
答案 0 :(得分:7)
由于this_r
是静态成员,因此您始终可以访问它而无需取消引用(非constexpr)对对象实例的引用,从而使clang或其他编译器满意:
int f(std::variant<S<0>, S<1>, S<2> > v) {
return std::visit([](auto const& arg) {
if constexpr(::std::remove_reference_t<decltype(arg)>::this_r == 0) { return 42; }
else { return ::std::remove_reference_t<decltype(arg)>::this_r; }
}, v);
}