- concepts[meta header]
- cpp20[meta cpp]
<concepts>
ヘッダでは基礎的なコンセプトの実装を提供する。これらのコンセプトは標準ライブラリでも使用される。
本ヘッダはフリースタンディング環境でも提供される。
ある式への等しい入力によって等しい出力が得られる時、その式は 等しさを保持 している。入力とはその式に与えられた全ての引数(オペランド)であり、出力とはその式の結果およびその式によって変更された全ての引数のこと。
また、必ずしも入力の個別の値が全てその式にとって有効である必要はない。例えば、整数に対するa / b
という式は等しさを保持するが、b = 0
の時この式は有効ではない。しかし、このことは式a / b
が等しさを保持することを妨げない。
式への入力のうちこのような有効ではない値を除いたものをその式の 定義域(domain) と呼ぶ。
等しさを保持する式はさらに 安定(stable) でなければならない。式が安定であるとは、その式への同じオブジェクトの入力は、そのオブジェクトの明示的な変更が介在しない限りは常に同じ出力が得られることである。
式が安定であれば、あるオブジェクトの現在の値についてのことを、等しさを保持する式を介して観測した以前の値についての情報から推察することができる。
つまりこれらの事は、式が引数と結果以外に副作用を及ぼさず、式内部に状態を持たず、式の実行にはその外部からの影響がないことを要求している。
そして、C++標準においてrequires
式で使用される全ての式は等しさを保持し安定でなければならない。この事は、場合によっては間接的にユーザーコードに対しても要求される。ただし、「等しさを保持することを要求しない」などと明記されている場合にはその必要はない。
C++標準で定義されるrequires
式では、それぞれの制約式への入力が(その制約式が実際に実行された場合に)変更されるかどうかをrequires
式のローカルパラメータのconst
修飾によって表現する。別に記載のある場合を除いて、const
修飾のない左辺値・右辺値のローカルパラメータは変更しても良く変更されうる事を、const
修飾されたパラメータは変更してはならず変更されない事を表明する。
template<typename T>
concept C1 = requires(T a) {
a + a; // C1コンセプトを満たす型はこの式の実行においてその引数を変更しても良い
};
template<typename T>
concept C2 = requires(const T a) {
a + a; // C2コンセプトを満たす型はこの式の実行においてその引数を変更してはならない
};
これによって各制約式では、型パラメータがCV修飾されない非配列のオブジェクト型であると仮定することで、それぞれの引数の値カテゴリとCV修飾を確定することができる。
requires
式において定数左辺値としてローカルパラメータを宣言する場合、それぞれの制約式にはそのパラメータを受け取る位置に非定数左辺値や(定数)右辺値を受け入れる暗黙的な式のバリエーションが要求される。ただし、このような暗黙的な式のバリエーション(のいずれか)が異なる意味論を持ち、明示的に記述される場合を除く。
この暗黙的な式のバリエーションは各制約式の意味論的な要件を満たすために必要である。ただし、実装が各バリエーションをどこまで構文的に検証するかについては未規定。
// このCコンセプトは
template<typename T>
concept C = requires(const T a, T b) {
a + b;
};
// 以下のようなバリエーションが全て有効であることを暗黙的に要求している(実際にこのように検証されるかは未規定)
template<typename T>
concept C =
requires(const T a, T b) { a + b } &&
requires(T a, T b) { a + b; } &&
requires(T&& a, T b) { std::move(a) + b; } &&
requires(const T&& a, T b) { std::move(a) + b; };
型T
があるコンセプトC
の構文的な制約(コンセプト定義内の各制約式)を全て満足しそれら制約式の追加の暗黙の意味論的な制約(等しさの保持、安定、入力への副作用の要求および暗黙的な式のバリエーション)についても全て満足していて、C
に追加で要求されている意味論的な制約(モデルとなる条件)を全て満足するとき、そのような型T
はコンセプトC
の モデル(model) である。
モデルとなるための意味論的な制約は文書で指定されているのみであり、通常何らかのチェックは行われない。しかし、標準ライブラリの事前条件などにおいて入力に対してあるコンセプトのモデルである事を要求する場合、モデルとならない型の入力は診断不要の未定義動作となる。
本サイトでは、型がコンセプトのモデルとなるための条件をそのコンセプトの構文的な制約条件とは分けて「モデル」という項に記載する。
名前 | 説明 | 対応バージョン |
---|---|---|
same_as |
2つの型が同じ | C++20 |
derived_from |
継承関係にある | C++20 |
convertible_to |
変換可能 | C++20 |
common_reference_with |
共通の参照型 | C++20 |
common_with |
共通の型 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
integral |
整数型 | C++20 |
signed_integral |
符号付き整数型 | C++20 |
unsigned_integral |
符号なし整数型 | C++20 |
floating_point |
浮動小数点数型 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
constructible_from |
構築可能 | C++20 |
default_initializable |
デフォルト構築可能 | C++20 |
copy_constructible |
コピー構築可能 | C++20 |
move_constructible |
ムーブ構築可能 | C++20 |
destructible |
破棄可能 | C++20 |
assignable_from |
代入可能 | C++20 |
swappable |
入れ替え可能 | C++20 |
swappable_with |
特定の型と入れ替え可能 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
equality_comparable |
等値比較可能 | C++20 |
equality_comparable_with |
特定の型と等値比較可能 | C++20 |
totally_ordered |
狭義の全順序による比較が可能 | C++20 |
totally_ordered_with |
特定の型と狭義の全順序による比較が可能 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
movable |
ムーブ可能 | C++20 |
copyable |
コピー可能 | C++20 |
semiregular |
半正則 | C++20 |
regular |
正則 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
invocable |
INVOKEコンセプトに従った関数呼び出しが可能 | C++20 |
regular_invocable |
正則呼び出し可能 | C++20 |
predicate |
述語 | C++20 |
relation |
二項関係 | C++20 |
equivalence_relation |
同値関係 | C++20 |
strict_weak_order |
狭義の弱順序 | C++20 |
名前 | 説明 | 対応バージョン |
---|---|---|
ranges::swap |
任意の2つのオブジェクトを入れ替える | C++20 |
以下は、ライブラリとして提供はされていない要件をまとめる。
名前 | 説明 |
---|---|
Callable |
|
INVOKE |
|
LessThanComparable |
小なり比較可能 |
ValueSwappable |
間接参照して入れ替え可能 |
CopyAssignable |
コピー代入可能 |
MoveAssignable |
ムーブ代入可能 |