概念庫 (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 施加嚴格弱序(概念) |