【发布时间】:2019-07-10 08:38:34
【问题描述】:
我想编写一个通用 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 抱怨 if constexpr 的 arg.this_r == 0 参数不是恒定的,回到 version 4.0.0 但这仍然存在于 current trunk 中。
谁是正确的,我怎样才能避免这个问题(假设一个简单的if 不会削减它,因为两个分支之一是不可实例化的)?
附录:将 arg 作为值而不是 const 左值引用传递,Clang is happy,但不幸的是,这不是我的选择。
【问题讨论】:
-
我认为 lambda 参数
arg不是constexpr这里。不过我不确定。 -
arg本身当然不是 constexpr,但它的成员this_r是。一旦知道arg的类型,arg.this_r应该是 constexpr? -
@Claudius 否,因为
arg.this_r是非 constexpr 对象的成员访问表达式。std::remove_cvref_t<decltype(arg)>::this_r是一个常量表达式,因为它不使用成员访问表达式。 -
嗯,进一步研究后,可能 Clang 有一个错误。 MSVC、Intel 和 GCC 都同意没关系:godbolt.org/z/0RcsLC
-
@JonathanWakely 我认为这是一个标准错误,我认为它在技术上不正确,但不应该如此。
标签: c++ c++17 variant generic-lambda