铛声称通用lambda参数的constexpr成员不是constexpr

时间:2019-07-10 08:38:34

标签: c++ c++17 variant generic-lambda

我想写一个通用的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进行传递,但不幸的是,这不是我的选择。

1 个答案:

答案 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);
}

online compiler