コンセプトライブラリ (C++20以降)
コンセプトライブラリは、テンプレート引数のコンパイル時検証や、型のプロパティに基づいた関数のディスパッチに使用できる、基本的なライブラリコンセプトの定義を提供します。これらのコンセプトは、プログラムにおける等式推論 (equational reasoning) のための基盤を提供します。
標準ライブラリのほとんどのコンセプトは、構文要件と意味論的要件の両方を課します。ある標準コンセプトは、その構文要件が満たされている場合に充足している (satisfied) と言われ、構文要件に加えて意味論的要件(もしあれば)も満たされている場合にモデル化している (modeled) と言われます。
一般的に、コンパイラによってチェックできるのは構文要件のみです。プログラムの妥当性や意味が、テンプレート引数のシーケンスがコンセプトをモデル化しているかどうかに依存する場合で、コンセプトが充足しているがモデル化していない、あるいは意味論的要件が使用時点で満たされていない場合、プログラムは不適格 (ill-formed) となり、診断不用 (no diagnostic required) です。
目次 |
[編集] 等価性の維持
ある式は、等しい入力に対して等しい出力を生成する場合、等価性を維持する (equality-preserving) と言われます。ここで、
- 入力はそのオペランドから構成され(式が意味論的に有効である必要はない)、
- 出力はその結果と、式によるオペランドへのすべての変更(もしあれば)から構成されます。
ここで、記述の便宜上、「オペランド」とは、id-expression、またはstd::move、std::forward、std::declvalの呼び出しで構成される最大のサブ式を指します。
各オペランドのcv修飾と値カテゴリは、その型に含まれる各テンプレート型パラメータが、cv修飾されていない完全な非配列オブジェクト型を表すと仮定して決定されます。
等価性を維持することが要求されるすべての式は、さらに安定していること、つまり、同じ入力オブジェクトに対する2つの評価が、それらの入力オブジェクトを明示的に変更することなく、等しい出力を持つことが要求されます。
特に断りのない限り、標準ライブラリのコンセプトのrequires 式で使用されるすべての式は、等価性を維持することが要求され、その式の評価は非constなオペランドのみを変更することができます。constなオペランドは変更してはなりません。
標準ライブラリでは、以下のコンセプトは等価性を維持しないrequires 式を持つことが許されています。
[編集] 暗黙の式のバリエーション
あるconst左辺値オペランドに対して変更を行わない式を使用するrequires 式は、そのオペランドに対して非const左辺値または(constである可能性のある)右辺値を受け入れる追加のバリエーションも暗黙的に要求します。ただし、そのような式のバリエーションが異なるセマンティクスで明示的に要求されている場合は除きます。
これらの暗黙の式のバリエーションは、宣言された式と同じ意味論的要件を満たさなければなりません。実装がこれらのバリエーションの構文をどの程度検証するかは未規定です。
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) |
2つの型が共通の参照型を共有することを規定する (コンセプト) |
| (C++20) |
2つの型が共通の型を共有することを規定する (コンセプト) |
| (C++20) |
型が整数型であることを規定する (コンセプト) |
| (C++20) |
型が符号付き整数型であることを規定する (コンセプト) |
| (C++20) |
型が符号無し整数型であることを規定する (コンセプト) |
| (C++20) |
型が浮動小数点型であることを規定する (コンセプト) |
| (C++20) |
型が別の型から代入可能であることを規定する (コンセプト) |
| (C++20) |
型が交換可能であること、または2つの型が互いに交換可能であることを規定する (コンセプト) |
| (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) |
呼び出し可能型が真偽値を返す述語 (Boolean predicate) であることを規定する (コンセプト) |
| (C++20) |
呼び出し可能型が二項関係 (binary relation) であることを規定する (コンセプト) |
| (C++20) |
relationが同値関係を課すことを規定する(コンセプト) |
| (C++20) |
relationが狭義の弱順序を課すことを規定する(コンセプト) |
追加のコンセプトは、イテレータライブラリ、アルゴリズムライブラリ、およびRangeライブラリにあります。