概念库 (C++20 起)
概念库提供了基本库概念的定义,这些概念可用于对模板参数执行编译时验证,并根据类型的属性执行函数分派。这些概念为程序中的等式推理提供了基础。
标准库中的大多数概念都施加了句法和语义要求。如果满足其句法要求,则称标准概念为 _satisfied_;如果满足其句法要求并且也满足其语义要求(如果有),则称其为 _modeled_。
通常,只有句法要求可以由编译器检查。如果程序的有效性或含义取决于模板参数序列是否 _models_ 一个概念,并且该概念被 _satisfied_ 但未被 _modeled_,或者如果在使用点未满足语义要求,则程序格式错误,无需诊断。
目录 |
[编辑] 相等性保持
如果一个表达式在给定相等输入时产生相等输出,则称该表达式是 _equality-preserving_ 的,其中
- 输入由其操作数组成(不一定使表达式在语义上有效),并且
- 输出由其结果以及表达式对操作数(如果有)的所有修改组成
为方便起见,其“操作数”指其最大的子表达式,这些子表达式由 id-expression 或对 std::move、std::forward 和 std::declval 的调用组成。
每个操作数的 cv 限定和值类别通过假设其类型中的每个模板类型参数表示一个 cv 非限定的完整非数组对象类型来确定。
所有要求相等性保持的表达式还要求是稳定的,即,两次使用相同输入对象进行求值必须产生相等输出,而无需对这些输入对象进行任何显式中间修改。
除非另有说明,否则标准库概念的 requires 表达式中使用的每个表达式都要求是相等性保持的,并且表达式的求值只能修改其非常量操作数。常量操作数不得修改。
在标准库中,以下概念允许具有非相等性保持的 requires 表达式
[编辑] 隐式表达式变体
一个 requires 表达式,如果它使用了对某个常量左值操作数不进行修改的表达式,则它也隐式地要求该表达式的额外变体,这些变体接受非常量左值或(可能是常量)右值作为给定操作数,除非明确要求具有不同语义的此类表达式变体。
这些 _隐式表达式变体_ 必须满足声明表达式的相同语义要求。实现验证变体语法的程度未指定。
template<class T> concept C = requires(T a, T b, const T c, const T d) { c == d; // expression #1: does not modify the operands a = std::move(b); // expression #2: modifies both operands a = c; // expression #3: modifies the left operand `a` }; // Expression #1 implicitly requires additional expression variations that // meet the requirements for c == d (including non-modification), // as if the following expressions had been declared as well: // ------ 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); // Expression #3 implicitly requires additional expression variations that // meet the requirements for a = c // (including non-modification of the second operand), // as if the expressions a = b (non-constant lvalue variation) // and a = std::move(c) (const rvalue variation) had been declared. // Note: Since expression #2 already requires the non-constant rvalue variation // (a == std::move(b)) explicitly, expression #3 does not implicitly require it anymore. // The type T meets the explicitly stated syntactic requirements of // concept C above, but does not meet the additional implicit requirements // (i.e., T satisfies but does not model C): // a program requires C<T> is ill-formed (no diagnostic required). 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) |
指定两种类型共享一个共同的类型 (概念) |
(C++20) |
指定类型是整型 (概念) |
(C++20) |
指定类型是带符号的整型 (概念) |
(C++20) |
指定类型是无符号的整型 (概念) |
(C++20) |
指定类型是浮点类型 (概念) |
(C++20) |
指定类型可从另一类型赋值 (概念) |
(C++20) |
指定类型可以被交换,或者两种类型可以互相交换 (概念) |
(C++20) |
指定该类型的对象可以被销毁 (概念) |
(C++20) |
指定该类型的变量可以从一组参数类型构造或绑定 (概念) |
(C++20) |
指定类型的对象可以默认构造 (概念) |
(C++20) |
指定类型的对象可以被移动构造 (概念) |
(C++20) |
指定类型的对象可以被复制构造和移动构造 (概念) |
比较概念 | |
定义于头文件
<concepts> | |
(C++20) |
指定类型可以在布尔上下文中使用 (仅用于阐释的概念*) |
指定运算符 == 是等价关系 (概念) | |
指定类型上的比较运算符产生全序关系 (概念) | |
定义于头文件
<compare> | |
指定运算符 <=> 在给定类型上产生一致的结果 (概念) | |
对象概念 | |
定义于头文件
<concepts> | |
(C++20) |
指定类型的对象可以被移动和交换 (概念) |
(C++20) |
指定类型的对象可以被复制、移动和交换 (概念) |
(C++20) |
指定类型的对象可以被复制、移动、交换和默认构造 (概念) |
(C++20) |
指定类型是 _regular_ 的,即它既是 semiregular 又是 equality_comparable (概念) |
可调用概念 | |
定义于头文件
<concepts> | |
(C++20) |
指定可调用类型可以使用给定的一组参数类型进行调用 (概念) |
(C++20) |
指定可调用类型是布尔谓词 (概念) |
(C++20) |
指定可调用类型是二元关系 (概念) |
(C++20) |
指定 relation 施加等价关系(概念) |
(C++20) |
指定 relation 施加严格弱序(概念) |