イテレータライブラリ
イテレータはポインタを一般化したものであり、C++プログラムが様々なデータ構造(例えば、コンテナやRange(C++20から))を統一的な方法で扱えるようにするものです。イテレータライブラリは、イテレータの定義、イテレータのトレイト、アダプタ、およびユーティリティ関数を提供します。
イテレータはポインタの抽象化であるため、そのセマンティクスはC++におけるポインタのセマンティクスのほとんどを一般化したものです。これにより、イテレータを受け取るすべての関数テンプレートが、通常のポインタでも同様に機能することが保証されます。
目次 |
[編集] イテレータカテゴリ
イテレータには5(C++17まで)6(C++17から)種類のカテゴリがあります:LegacyInputIterator, LegacyOutputIterator, LegacyForwardIterator, LegacyBidirectionalIterator, LegacyRandomAccessIterator, および LegacyContiguousIterator(C++17から)。(最も基本的な種類のイテレータについてはLegacyIteratorも参照してください。)
イテレータの各カテゴリは特定の型によって定義されるのではなく、そのイテレータに対して実行できる操作によって定義されます。この定義は、必要な操作をサポートする任意の型がイテレータとして使用できることを意味します。たとえば、ポインタはLegacyRandomAccessIteratorで要求されるすべての操作をサポートするため、LegacyRandomAccessIteratorが期待される場所であればどこでもポインタを使用できます。
(LegacyOutputIteratorを除く)すべてのイテレータカテゴリは階層構造に整理でき、より強力なイテレータカテゴリ(例:LegacyRandomAccessIterator)は、より能力の低いカテゴリ(例:LegacyInputIterator)の操作をサポートします。あるイテレータがこれらのカテゴリのいずれかに属し、かつLegacyOutputIteratorの要件も満たす場合、それは可変 (mutable)イテレータと呼ばれ、入力と出力の両方をサポートします。非可変イテレータは定数 (constant)イテレータと呼ばれます。
|
イテレータカテゴリの要件を満たすために提供されるすべての操作がconstexpr関数である場合、そのイテレータはconstexprイテレータと呼ばれます。 |
(C++20以降) |
| イテレータカテゴリ | 操作とストレージ要件 | ||||||
|---|---|---|---|---|---|---|---|
| 書き込み | 読み取り | インクリメント | デクリメント | ランダム アクセス |
連続 ストレージ | ||
| なし マルチパス パス |
あり マルチパス パス | ||||||
| LegacyIterator | 必須 | ||||||
| LegacyOutputIterator | 必須 | 必須 | |||||
| LegacyInputIterator (書き込み操作をサポートする場合は可変) |
必須 | 必須 | |||||
| LegacyForwardIterator (LegacyInputIteratorも満たす) |
必須 | 必須 | 必須 | ||||
| LegacyBidirectionalIterator (LegacyForwardIteratorも満たす) |
必須 | 必須 | 必須 | 必須 | |||
| LegacyRandomAccessIterator (LegacyBidirectionalIteratorも満たす) |
必須 | 必須 | 必須 | 必須 | 必須 | ||
| LegacyContiguousIterator[1] (LegacyRandomAccessIteratorも満たす) |
必須 | 必須 | 必須 | 必須 | 必須 | 必須 | |
- ↑ LegacyContiguousIteratorカテゴリはC++17で正式に規定されましたが、std::vector、std::basic_string、std::array、std::valarrayのイテレータ、およびC配列へのポインタは、C++17以前のコードではしばしば別のカテゴリとして扱われます。
注意:上の表の行で要求される操作をサポートする型が、必ずしも対応するカテゴリに分類されるわけではありません。要件の完全なリストについては、各カテゴリのページを参照してください。
[編集] 定義
[編集] 型と書き込み可能性
入力イテレータ i は式 *i をサポートし、その結果は何らかのオブジェクト型 T の値となり、これはイテレータの値型 (value type) と呼ばれます。
出力イテレータ i は、そのイテレータに対して書き込み可能 (writable)(C++20まで)indirectly_writable(C++20から)である型の非空の集合を持ちます。そのような各型 T について、o が型 T の値である場合、式 *i = o は有効です。
等価性が定義されている(C++20まで)すべてのイテレータ型 X について、対応する符号付きの整数(C++20まで)整数のような (integer-like)(C++20から)型が存在し、これはイテレータの差分型 (difference type) と呼ばれます。
[編集] 間接参照可能性と有効性
配列への通常のポインタが、配列の最後の要素の次を指すポインタ値が存在することを保証するように、任意のイテレータ型についても、対応するシーケンスの最後の要素の次を指すイテレータ値が存在します。このような値は過去終端 (past-the-end) 値と呼ばれます。
イテレータ i の値のうち、式 *i が定義されるものは間接参照可能 (dereferenceable) と呼ばれます。標準ライブラリは、過去終端値が間接参照可能であるとは決して仮定しません。
イテレータは、どのシーケンスにも関連付けられていない特異 (singular) な値を持つこともあります。特異な値に対するほとんどの式の結果は未定義です。唯一の例外は次の通りです。
- 特異な値を保持するイテレータへの非特異な値の代入
- 特異な値を保持するイテレータの破棄、および、
- DefaultConstructible 要件を満たすイテレータについて、値初期化されたイテレータをコピーまたはムーブ(C++11から)操作のソースとして使用すること。
これらの場合、特異な値は他の値と同様に上書きされます。間接参照可能な値は常に非特異です。
無効 (invalid) なイテレータとは、特異である可能性のあるイテレータです。
[編集] Range (範囲)
データ構造を操作する標準ライブラリのアルゴリズムテンプレートのほとんどは、Rangeを使用するインターフェースを持っています。
|
イテレータ j は、式 ++i の有限回の適用によって i == j となるとき、かつそのときに限り、イテレータ i から到達可能 (reachable) であると呼ばれます。j が i から到達可能である場合、それらは同じシーケンスの要素を参照します。 Range (範囲) は、計算の開始と終了を指定するイテレータのペアです。Range Range |
(C++20まで) |
|
Rangeは、以下のいずれかによって示されます。
イテレータ-番兵 (sentinel) 範囲Rangeを示すイテレータと番兵は比較可能です。i == s の場合、 番兵 s は、式 ++i の有限回の適用によって i == s となるとき、かつそのときに限り、イテレータ i から到達可能 (reachable) と呼ばれます。 s が i から到達可能である場合、 計数範囲計数範囲 (counted range) i 計数範囲 i
|
(C++20以降) |
無効なRangeに対して標準ライブラリの関数を適用した結果は未定義です。
[編集] イテレータのコンセプト (C++20以降)
C++17のイテレータとは異なる、コンセプトに基づいた新しいイテレータの体系。基本的な分類は似ていますが、個々のイテレータカテゴリの要件はいくらか異なります。
| 名前空間
std で定義 | |
| (C++20) |
型が演算子 * を適用することで間接的に読み取り可能であることを規定する(コンセプト) |
| (C++20) |
イテレータが参照するオブジェクトに値を書き込めることを規定する (コンセプト) |
| (C++20) |
semiregular 型が前置および後置インクリメント演算子でインクリメントできることを規定する(コンセプト) |
| (C++20) |
weakly_incrementable 型のインクリメント操作が等価性を保持し、その型がequality_comparable であることを規定する(コンセプト) |
| (C++20)(C++20) |
型が(符号付き)整数型のように振る舞うことを規定する (説明専用コンセプト*) |
| (C++20) |
ある型のオブジェクトがインクリメントおよび間接参照できることを規定する (コンセプト) |
| (C++20) |
input_or_output_iterator 型に対する番兵 (sentinel) であることを規定する(コンセプト) |
| (C++20) |
演算子 - をイテレータと番兵 (sentinel) に適用して、定数時間でその差を計算できることを規定する (コンセプト) |
| (C++20) |
型が入力イテレータであること、すなわち、参照先の値を読み取ることができ、前置および後置インクリメントの両方が可能であることを規定する (コンセプト) |
| (C++20) |
型が与えられた値型に対する出力イテレータであること、すなわち、その型の値を書き込むことができ、前置および後置インクリメントの両方が可能であることを規定する (コンセプト) |
| (C++20) |
input_iterator が、等価比較とマルチパスをサポートする前方イテレータであることを規定する(コンセプト) |
| (C++20) |
forward_iterator が、後方への移動をサポートする双方向イテレータであることを規定する(コンセプト) |
| (C++20) |
bidirectional_iterator が、定数時間での移動と添字演算をサポートするランダムアクセスイテレータであることを規定する(コンセプト) |
| (C++20) |
random_access_iterator が、メモリ上で連続している要素を参照する連続イテレータであることを規定する(コンセプト) |
[編集] イテレータの関連型 (C++20以降)
| 名前空間
std で定義 | |
| (C++20) |
weakly_incrementable 型の差分型を計算する(クラステンプレート) |
| (C++20) |
indirectly_readable 型の値型を計算する(クラステンプレート) |
| (C++20)(C++20)(C++23)(C++20)(C++20)(C++20) |
イテレータの関連型を計算する (エイリアステンプレート) |
[編集] イテレータのプリミティブ
| イテレータのプロパティへの統一的なインターフェースを提供する (クラステンプレート) | |
| イテレータカテゴリを示すために使用される空のクラス型 (クラス) | |
| (C++17で非推奨) |
単純なイテレータに必要な型の定義を容易にするための基底クラス (クラステンプレート) |
[編集] イテレータのカスタマイゼーションポイント (C++20以降)
| 名前空間
std::ranges で定義 | |
| (C++20) |
オブジェクトの間接参照の結果を、その関連する右辺値参照型にキャストする (カスタマイゼーションポイントオブジェクト) |
| (C++20) |
2つの間接参照可能なオブジェクトが参照する値を交換する (カスタマイゼーションポイントオブジェクト) |
[編集] アルゴリズムのコンセプトとユーティリティ (C++20以降)
共通のアルゴリズム操作を制約しやすくするために設計された、コンセプトと関連ユーティリティテンプレートのセット。
| ヘッダ
<iterator> で定義 | |
| 名前空間
std で定義 | |
間接呼び出し可能コンセプト | |
呼び出し可能な型が、indirectly_readable 型の間接参照の結果で呼び出せることを規定する(コンセプト) | |
| (C++20) |
呼び出し可能な型が、indirectly_readable 型の間接参照の結果で呼び出されたときに predicate を満たすことを規定する(コンセプト) |
| (C++20) |
呼び出し可能な型が、2つの indirectly_readable 型の間接参照の結果で呼び出されたときに predicate を満たすことを規定する(コンセプト) |
呼び出し可能な型が、2つの indirectly_readable 型の間接参照の結果で呼び出されたときに equivalence_relation を満たすことを規定する(コンセプト) | |
| (C++20) |
呼び出し可能な型が、2つの indirectly_readable 型の間接参照の結果で呼び出されたときに strict_weak_order を満たすことを規定する(コンセプト) |
共通アルゴリズム要件 | |
| (C++20) |
indirectly_readable 型から indirectly_writable 型へ値をムーブできることを規定する(コンセプト) |
| (C++20) |
indirectly_readable 型から indirectly_writable 型へ値をムーブでき、そのムーブが中間オブジェクトを介して実行できることを規定する(コンセプト) |
| (C++20) |
indirectly_readable 型から indirectly_writable 型へ値をコピーできることを規定する(コンセプト) |
| (C++20) |
indirectly_readable 型から indirectly_writable 型へ値をコピーでき、そのコピーが中間オブジェクトを介して実行できることを規定する(コンセプト) |
| (C++20) |
2つの indirectly_readable 型が参照する値を交換できることを規定する(コンセプト) |
| (C++20) |
2つの indirectly_readable 型が参照する値を比較できることを規定する(コンセプト) |
| (C++20) |
要素をインプレースで並べ替えるアルゴリズムの共通要件を規定する (コンセプト) |
| (C++20) |
ソート済みのシーケンスを要素をコピーして出力シーケンスにマージするアルゴリズムの要件を規定する (コンセプト) |
| (C++20) |
シーケンスを順序付きシーケンスに並べ替えるアルゴリズムの共通要件を規定する (コンセプト) |
ユーティリティ | |
| (C++20) |
いくつかの indirectly_readable 型の間接参照の結果に対して呼び出し可能オブジェクトを呼び出した結果を計算する(エイリアステンプレート) |
| (C++20) |
射影を受け入れるアルゴリズムの制約を指定するためのヘルパーテンプレート (クラステンプレート) |
| (C++26) |
射影によって indirectly_readable 型の値型を計算する(エイリアステンプレート) |
[編集] イテレータアダプタ
| 逆順走査のためのイテレータアダプタ (クラステンプレート) | |
| (C++14) |
引数から推論された型の std::reverse_iterator を作成する (関数テンプレート) |
| コンテナの末尾への挿入のためのイテレータアダプタ (クラステンプレート) | |
| 引数から推論された型の std::back_insert_iterator を作成する (関数テンプレート) | |
| コンテナの先頭への挿入のためのイテレータアダプタ (クラステンプレート) | |
| 引数から推論された型の std::front_insert_iterator を作成する (関数テンプレート) | |
| コンテナへの挿入のためのイテレータアダプタ (クラステンプレート) | |
| 引数から推論された型の std::insert_iterator を作成する (関数テンプレート) | |
| (C++23) |
イテレータを定数イテレータに変換するイテレータアダプタ (クラステンプレート) |
| (C++23) |
与えられた型に対する定数イテレータ型を計算する (エイリアステンプレート) |
| (C++23) |
定数イテレータと共に使用される番兵 (sentinel) 型を計算する (エイリアステンプレート) |
| (C++23) |
引数から推論された型の std::const_iterator を作成する (関数テンプレート) |
| (C++23) |
引数から推論された型の std::const_sentinel を作成する (関数テンプレート) |
| (C++11) |
間接参照すると右辺値になるイテレータアダプタ (クラステンプレート) |
| (C++20) |
std::move_iterator のための番兵 (sentinel) アダプタ (クラステンプレート) |
| (C++11) |
引数から推論された型の std::move_iterator を作成する (関数テンプレート) |
| (C++20) |
イテレータ型とその番兵 (sentinel) を共通のイテレータ型に適合させる (クラステンプレート) |
| (C++20) |
範囲の境界を知っているイテレータと共に使用するためのデフォルトの番兵 (sentinel) (クラス) |
| (C++20) |
範囲の終端までの距離を追跡するイテレータアダプタ (クラステンプレート) |
| (C++20) |
任意の weakly_incrementable 型と常に非等価となる番兵 (sentinel)(クラス) |
[編集] ストリームイテレータ
| std::basic_istream から読み取る入力イテレータ (クラステンプレート) | |
| std::basic_ostream に書き込む出力イテレータ (クラステンプレート) | |
| std::basic_streambuf から読み取る入力イテレータ (クラステンプレート) | |
| std::basic_streambuf に書き込む出力イテレータ (クラステンプレート) |
[編集] イテレータ操作
| ヘッダ
<iterator> で定義 | |
| イテレータを指定された距離だけ進める (関数テンプレート) | |
| 2つのイテレータ間の距離を返す (関数テンプレート) | |
| (C++11) |
イテレータをインクリメントする (関数テンプレート) |
| (C++11) |
イテレータをデクリメントする (関数テンプレート) |
| (C++20) |
イテレータを指定された距離または指定された境界まで進める (アルゴリズム関数オブジェクト) |
| (C++20) |
イテレータと番兵 (sentinel) の間の距離、またはRangeの始点と終点の間の距離を返す (アルゴリズム関数オブジェクト) |
| (C++20) |
イテレータを指定された距離または境界までインクリメントする (アルゴリズム関数オブジェクト) |
| (C++20) |
イテレータを指定された距離または境界までデクリメントする (アルゴリズム関数オブジェクト) |
[編集] Rangeアクセス (C++11以降)
これらの非メンバ関数テンプレートは、コンテナ、生の配列、および std::initializer_list のための汎用的なインターフェースを提供します。
| ヘッダー
<array> で定義 | |
| ヘッダー
<deque> で定義 | |
| ヘッダ
<flat_map> で定義 | |
| ヘッダ
<flat_set> で定義 | |
| ヘッダ
<forward_list> で定義 | |
| ヘッダ
<inplace_vector> で定義 | |
| ヘッダ
<iterator> で定義 | |
| ヘッダ
<list> で定義 | |
| ヘッダ
<map> で定義 | |
| ヘッダ
<regex> で定義 | |
| ヘッダ
<set> で定義 | |
| ヘッダ
<span> で定義 | |
| ヘッダ
<string> で定義 | |
| ヘッダ
<string_view> で定義 | |
| ヘッダ
<unordered_map> で定義 | |
| ヘッダー
<unordered_set> で定義 | |
| ヘッダ
<vector> で定義 | |
| 名前空間
std で定義 | |
| (C++11)(C++14) |
コンテナまたは配列の先頭を指すイテレータを返す (関数テンプレート) |
| (C++11)(C++14) |
コンテナまたは配列の末尾を指すイテレータを返す (関数テンプレート) |
| (C++14) |
コンテナまたは配列の先頭を指す逆順イテレータを返す (function template) |
| (C++14) |
コンテナまたは配列の逆順の終端イテレータを返す (function template) |
| (C++17)(C++20) |
コンテナまたは配列のサイズを返す (関数テンプレート) |
| (C++17) |
コンテナが空かどうかをチェックする (function template) |
| (C++17) |
背後にある配列へのポインタを取得する (function template) |
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 1181 | C++98 | 配列型は値型になれなかった | できるようになった |
| LWG 208 | C++98 | 過去終端イテレータは常に非特異だった | 特異になりうる |
| LWG 278 | C++98 | イテレータの有効性が定義されていなかった | 常に非特異であると定義された |
| LWG 324 | C++98 | 出力イテレータは値型を持っていた | 出力イテレータは代わりに書き込み可能型を持つ |
| LWG 407 | C++98 | 特異イテレータは破棄できなかった | 許可 |
| LWG 408 (N3066) |
C++98 | 特異イテレータはコピーできなかった | 値初期化されていれば許可される |
| LWG 1185 (N3066) |
C++98 | LegacyForwardIterator, LegacyBidirectionalIterator および LegacyRandomAccessIterator は常に LegacyOutputIterator を満たしていた |
それらは LegacyOutputIterator を満たさないかもしれない |
| LWG 1210 (N3066) |
C++98 | イテレータの特異性と 到達可能性の定義がコンテナに依存していた |
代わりにシーケンスに依存する |
| LWG 3009 | C++17 | <string_view> が Rangeアクセス関数テンプレートを提供していなかった |
これらのテンプレートを提供する |
| LWG 3987 | C++23 | <flat_map> と <flat_set> が Rangeアクセス関数テンプレートを提供していなかった |
これらのテンプレートを提供する |