C++ 概念,如何检查 constexpr static int 是否等于 1,或类似...?Clang 不同意 GCC 和 MSVC

Jor*_*dan 4 c++ constexpr c++-concepts c++20

我无法在cpprefference上找到与成员匹配的概念的正确语法static constexpr。此代码可以在 GCC 和 MSVC 上编译并正常运行,但在 Clang 中不起作用。我想知道是否有人知道这是我的错误,还是 GCC 和 MSVC 或 Clang 的问题?这是所有三个编译器都打开的Godbolt,我认为它说明了这一点!

#include <concepts>
#include <iostream>

template<typename T>
concept MyConcept = requires (T t){
    requires t.member == 1;

    //[clang's error]
    // note: because 't.member == 1' would be invalid: 
    //       constraint variable 't' cannot be used in an evaluated context
};

struct S {
    constexpr static int member {2};
};
struct D {
    constexpr static int member {1};
};

template<MyConcept T>
void func(){
    std::cout << "matched\n";
}

int main(){
    func<D>();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Bar*_*rry 5

Clang 在这里是正确的(谢谢,凯西)。

[expr.prim.req.nested] /2 说:

局部参数只能作为约束表达式中未计算的操作数出现。

[expr.ref]/1说:

后缀表达式后跟一个点.或箭头->,可选地后跟关键字 template,然后后跟id-expression,就是后缀表达式。计算点或箭头之前的后缀表达式;55 该计算的结果与 id 表达式一起确定整个后缀表达式的结果。

在 中t.member,评估t,并且我们不允许在这种情况下这样做。

表达这一点的另一种方式是完全删除需求主体并直接检查静态成员:

template<typename T>
concept MyConcept = T::member == 1;
Run Code Online (Sandbox Code Playgroud)

概念定义是任意布尔表达式,因此这就足够了并且不会违反任何规则。