temp.decls
concept是一个模板用于在模板参数上定义约束。
concept-definition:
concept concept-name = constraint-expression;
对于concept-definition有若干注意点,特别值得关注的而是:
- constraint-expression是unevalauted operand
- concept的第一个模板参数是其prototype parameter。一个type concept是这样的,其prototype parameter是一个类型的模板参数。
temp.constr
一个模板声明,或者一个模板化的函数声明可以通过requires-clause来约束其使用。约束是以constraint-expression形式提供:
constraint-expression:
logical-or-expression
约束也可以通过type-constraint的方式出现在template-parameter-list或者parameter-type-list中。
段3略。
temp
requires-clause:
requires constraint-logical-or-expression
constraint-logical-or-expression:
constraint-logical-and-expression
constraint-logical-or-expression || constraint-logical-and-expression
constraint-logical-and-expression:
primary-expression
constraint-logical-and-expression && primary-expression
requires-clause是一堆or或者and的递归形式,最终转化成primary-expression。
expr
primary-expression:
literal
this
( expression )
id-expression
lambda-expression
fold-expression
requires-expression
expr.prim.req
requires-expression提供一个简洁的方法来描述对于模板参数的需求,使其可以通过名字查找或者通过类型和表达式的属性的检查来判定需求是否满足。
requires-expression:
requires requirement-parameter-list(opt) requirement-body
requirement-parameter-list:
( parameter-declaration-clause )
requirement-body:
{ requirement-seq }
requirement-seq:
requirement
requirement-seq requirement
requirement:
simple-requirement
type-requirement
compound-requirement
nested-requirement
simple-requirement
expression ;
例子:
template<typename T> concept C =
requires (T a, T b) {
a + b; // C<T> is true if a + b is a valid expression
};
type-requirement:
typename nested-name-specifier(opt) type-name ;
例子:
template<typename T, typename T::type = 0> struct S;
template<typename T> using Ref = T&;
template<typename T> concept C = requires {
typename T::inner; // required nested member name
typename S<T>; // required valid ([temp.names]) template-id;
// fails if T::type does not exist as a type to which 0 can be implicitly converted
typename Ref<T>; // required alias template substitution, fails if T is void
};
compound-requirement:
{ expression } noexcept(opt) return-type-requirement(opt) ;
return-type-requirement:
-> type-constraint
例子:
requires {
{ E1 } -> C;
{ E2 } -> D<A1, ⋯, An>;
};
等同于:
requires {
E1; requires C<decltype((E1))>;
E2; requires D<decltype((E2)), A1, ⋯, An>;
};
nested-requirement:
requires constraint-expression ;
例子:
template<typename U> concept C = sizeof(U) == 1;
template<typename T> concept D = requires (T t) {
requires C<decltype (+t)>;
};
上述例子D<T>
在sizeof(decltype (+t)) == 1
被满足。
例子:
template<typename T> concept C = requires (T a) {
requires sizeof(a) == 4; // OK
requires a == 0; // error: evaluation of a constraint variable
};
其他参考
- https://devblogs.microsoft.com/cppblog/c20-concepts-are-here-in-visual-studio-2019-version-16-3/
- https://www.sandordargo.com/blog/2021/02/17/cpp-concepts-4-ways-to-use-them
- https://www.sandordargo.com/blog/2021/02/10/cpp-concepts-motivations
- https://www.cppstories.com/2021/concepts-intro/
- https://arne-mertz.de/2017/01/decltype-declval/
- https://en.cppreference.com/w/cpp/language/constraints
- https://en.cppreference.com/w/cpp/concepts
(暂时完了)