要求约束必须评估为 bool。所以没有 SFINAE

v.o*_*dou 2 c++ c++-concepts c++20

我对“原子约束”一章很好奇https://en.cppreference.com/w/cpp/language/constraints

它说

替换后 E 的类型必须恰好是 bool。不允许转换

f(0); // error: S<int>{} does not have type bool when checking #1,
          // even though #2 is a better match
Run Code Online (Sandbox Code Playgroud)

哎哟。这意味着在使用 require 子句时没有 SFINAE 机制?这不是很糟糕吗
因为我可以看到某些模板类型在遍历表达式后如何结果为 bool,但其他模板类型却看不到。现在我们又需要使用enable_if和东西了。痛得多?

Cas*_*sey 5

此限制的目的是使更难犯错误,从而导致不可满足或始终满足的概念,例如:

template<class T> concept C1 = sizeof(T); // Oops, I meant to write sizeof(T) >= 2
Run Code Online (Sandbox Code Playgroud)

如果sizeof(T)要隐式转换为bool,C将满足所有完整对象类型的要求。在实践中,您可以简单地将表达式强制转换为bool您真正想要的:

template<class T> concept C2 = (bool)sizeof(T); // I did *not* mean to write sizeof(T) >= 2
Run Code Online (Sandbox Code Playgroud)

请注意,当替换产生无效表达式时,概念不满足(https://godbolt.org/z/xMHoJ0):

template<class T> concept C3 = (bool)T::value;
static_assert(C3<std::true_type>);
static_assert(!C3<int>);
Run Code Online (Sandbox Code Playgroud)

或输入(https://godbolt.org/z/tnreG0):

template<class T> concept C4 = C3<typename T::type>;
static_assert(C4<std::is_same<int, int>>);
static_assert(!C4<int>);
Run Code Online (Sandbox Code Playgroud)

所以“要求子句不做 SFINAE!” 并不能准确描述情况。

我想我应该指出其他潜在的问题 - 原子约束表达式必须是常量表达式。如果替换到约束表达式中会产生非常量表达式,则该程序格式错误(https://godbolt.org/z/LQA1XQ):

template<class T> concept C5 = T::f();

struct S1 {
    static constexpr bool f() { return true; }
};

struct S2 {
    static constexpr bool f() { return false; }
};

struct S3 {
    static bool f() { return true; }
};

static_assert(!C5<void>); // Invalid expression: SFINAE and concept is not satisfied
static_assert(!C5<int>);  // Ditto

static_assert(C5<S1>);  // Constant expression that evaluates to true
static_assert(!C5<S2>); // Constant expression that evaluates to false

static_assert(C5<S3>);  // Ill-formed: not a constant expression
Run Code Online (Sandbox Code Playgroud)