此限制的目的是使错误更难导致不满意或始终满足的概念,例如:
template<class T> concept C1 = sizeof(T); // Oops, I meant to write sizeof(T) >= 2
如果
sizeof(T)
将隐式转换为
bool
,
C
会满足所有完整的对象类型。实际上,您可以简单地将表达式强制转换为
布尔
如果这是你真正想要的:
template<class T> concept C2 = (bool)sizeof(T); // I did *not* mean to write sizeof(T) >= 2
注意,当替换产生无效表达式时,概念是不满足的。(
https://godbolt.org/z/xMHoJ0
)以下内容:
template<class T> concept C3 = (bool)T::value;
static_assert(C3<std::true_type>);
static_assert(!C3<int>);
或类型(
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>);
所以“要求条款不适用于sfinae!”不能准确描述情况。
我想我应该指出另一个潜在的gotcha-原子约束表达式必须是常量表达式。如果替换为约束表达式生成一个非常量表达式,则程序格式错误(
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