要求约束必须评估为 bool。所以没有SFINAE
requires constraint must evaluate to bool. so no SFINAE
我对章节很好奇"atomic constraints"https://en.cppreference.com/w/cpp/language/constraints
它说
The type of E after substitution must be exactly bool. No conversion
is permitted
和
f(0); // error: S<int>{} does not have type bool when checking #1,
// even though #2 is a better match
哎呀。这意味着在使用 require 子句时 没有 SFINAE 机制?是不是很可惜?
因为我可以看到某些模板类型在通过表达式后如何产生 bool,而其他模板类型则不然。现在我们又需要使用 enable_if
之类的东西了。疼吗?
此限制的目的是使导致无法满足或始终满足的概念的错误变得更难,例如:
template<class T> concept C1 = sizeof(T); // Oops, I meant to write sizeof(T) >= 2
如果 sizeof(T)
隐式转换为 bool
,C
将满足所有完整对象类型的要求。实际上,您可以简单地将表达式强制转换为 bool
如果那是您真正想要的:
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>);
所以 "requires-clauses don't do 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
我对章节很好奇"atomic constraints"https://en.cppreference.com/w/cpp/language/constraints
它说
The type of E after substitution must be exactly bool. No conversion is permitted
和
f(0); // error: S<int>{} does not have type bool when checking #1,
// even though #2 is a better match
哎呀。这意味着在使用 require 子句时 没有 SFINAE 机制?是不是很可惜?
因为我可以看到某些模板类型在通过表达式后如何产生 bool,而其他模板类型则不然。现在我们又需要使用 enable_if
之类的东西了。疼吗?
此限制的目的是使导致无法满足或始终满足的概念的错误变得更难,例如:
template<class T> concept C1 = sizeof(T); // Oops, I meant to write sizeof(T) >= 2
如果 sizeof(T)
隐式转换为 bool
,C
将满足所有完整对象类型的要求。实际上,您可以简单地将表达式强制转换为 bool
如果那是您真正想要的:
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>);
所以 "requires-clauses don't do 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