Concepts library (since C++20)
概念库提供了基础库概念的定义,可用于执行模板参数的编译时验证,并根据类型属性执行函数分派。这些概念为程序中的等式推理提供了基础。
标准库中的大多数概念同时施加了语法要求和语义要求。当一个标准概念的语法要求被满足时,我们称其被 满足 ;若该概念同时满足其语义要求(如果存在),则称其被 建模 。
通常来说,编译器只能检查语法要求。如果程序的合法性或含义取决于模板参数序列是否对概念进行建模,而概念被满足但未被建模,或者在使用点未满足语义要求,则程序非良构, 不要求诊断 。
目录 |
等值保持
一个表达式是 保等性的 ,如果它在给定相等输入的情况下产生相等输出,其中
- 输入包含其操作数(不必然使表达式在语义上有效),以及
- 输出包含其结果及表达式对操作数的所有修改(若有)
其中,为表述方便,其"操作数"指的是由 标识表达式 或对 std::move 、 std::forward 及 std::declval 的调用所构成的最大子表达式。
每个操作数的 cv 限定和值类别通过假定其类型中的每个模板类型参数表示一个 cv 非限定的完整非数组对象类型来确定。
所有要求保持相等性的表达式进一步要求是稳定的,也就是说,对同一输入对象进行两次求值必须产生相等的输出,且期间不得对这些输入对象进行任何显式的修改。
除非另有说明,标准库概念的 requires expression 中使用的每个表达式都必须保持相等性,且该表达式的求值仅可修改其非常量操作数。常量操作数不得被修改。
在标准库中,以下概念允许具有非保序的 requires 表达式:
隐式表达式变体
一个 requires 表达式 若其使用的表达式对某个常量左值操作数具有非修改性质,则会隐式要求该表达式还需接受非常量左值或(可能为常量的)右值作为该操作数的其他变体,除非具有不同语义的表达式变体已被显式要求。
这些 隐式表达式变体 必须满足与声明表达式相同的语义要求。实现对这些变体语法验证的程度未作规定。
template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // 表达式 #1:不修改操作数 a = std::move(b); // 表达式 #2:修改两个操作数 a = c; // 表达式 #3:修改左操作数 `a` }; // 表达式 #1 隐式要求满足 c == d 要求(包括非修改性)的额外表达式变体, // 如同以下表达式也被声明: // ------ const == const ------- ------ const == non-const --- // c == b; // c == std::move(d); c == std::move(b); // std::move(c) == d; std::move(c) == b; // std::move(c) == std::move(d); std::move(c) == std::move(b); // -- non-const == const ------- -- non-const == non-const --- // a == d; a == b; // a == std::move(d); a == std::move(b); // std::move(a) == d; std::move(a) == b; // std::move(a) == std::move(d); std::move(a) == std::move(b); // 表达式 #3 隐式要求满足 a = c 要求 // (包括不修改第二个操作数)的额外表达式变体, // 如同表达式 a = b(非常量左值变体) // 和 a = std::move(c)(常量右值变体)已被声明。 // 注意:由于表达式 #2 已显式要求非常量右值变体 // (a == std::move(b)),表达式 #3 不再隐式要求该变体。 // 类型 T 满足上述概念 C 显式陈述的语法要求, // 但不满足额外的隐式要求 // (即 T 满足但不建模 C): // 要求 C<T> 的程序非良构(不要求诊断)。 struct T { bool operator==(const T&) const { return true; } bool operator==(T&) = delete; };
标准库概念
|
定义于 命名空间
std
|
|
核心语言概念 |
|
|
定义于头文件
<concepts>
|
|
|
(C++20)
|
指定一个类型与另一个类型相同
(概念) |
|
(C++20)
|
指定某个类型派生自另一个类型
(概念) |
|
(C++20)
|
指定某个类型可隐式转换为另一类型
(概念) |
|
(C++20)
|
指定两种类型共享一个公共引用类型
(概念) |
|
(C++20)
|
指定两种类型共享一个公共类型
(concept) |
|
(C++20)
|
指定类型为整型
(概念) |
|
(C++20)
|
指定类型为有符号整型
(概念) |
|
(C++20)
|
指定类型为无符号整型
(concept) |
|
(C++20)
|
指定类型为浮点类型
(concept) |
|
(C++20)
|
指定某个类型可从另一类型赋值
(概念) |
|
(C++20)
|
规定类型可交换或两种类型可相互交换
(concept) |
|
(C++20)
|
指定该类型的对象可以被销毁
(concept) |
|
(C++20)
|
规定该类型的变量可以从一组实参类型构造或绑定
(concept) |
|
(C++20)
|
指定某个类型的对象可被默认构造
(concept) |
|
(C++20)
|
指定该类型的对象可被移动构造
(概念) |
|
(C++20)
|
指定该类型的对象可被复制构造和移动构造
(概念) |
比较概念 |
|
|
定义于头文件
<concepts>
|
|
|
(C++20)
|
规定类型可在布尔上下文中使用
( 仅用于说明的概念* ) |
|
规定
==
运算符为等价关系
(概念) |
|
|
规定该类型上的比较运算符产生全序关系
(概念) |
|
|
定义于头文件
<compare>
|
|
|
规定
<=>
运算符在给定类型上产生一致结果
(concept) |
|
对象概念 |
|
|
定义于头文件
<concepts>
|
|
|
(C++20)
|
指定该类型的对象可被移动和交换
(concept) |
|
(C++20)
|
规定某个类型的对象可以被复制、移动和交换
(concept) |
|
(C++20)
|
规定该类型的对象可被复制、移动、交换及默认构造
(concept) |
|
(C++20)
|
规定类型是正则的,即它同时满足
semiregular
和
equality_comparable
(概念) |
可调用概念 |
|
|
定义于头文件
<concepts>
|
|
|
(C++20)
|
规定可调用类型可以使用给定参数类型集合进行调用
(concept) |
|
(C++20)
|
规定可调用类型为布尔谓词
(概念) |
|
(C++20)
|
规定可调用类型为二元关系
(concept) |
|
(C++20)
|
规定
relation
需施加等价关系
(概念) |
|
(C++20)
|
规定
relation
施加严格弱序关系
(概念) |