<ranges>
では、イテレータの組ではなく、コンテナや配列、部分的なコンテナなどの範囲(Range)を直接扱うライブラリを提供する。
C++17までは、標準アルゴリズム関数はイテレータの組を扱い、範囲を直接扱ってはいなかった。
このようなライブラリはBoost.Range、range-v3、cpplinqなどで実績があり、C++標準にも取り込まれることになった。
また、従来のイテレータの組は基本的に同じ型であることが期待されていたが、C++20のRangesではend
で得られるものは番兵(sentinel)と規定され、イテレータと同じ型でなくてもよくなった。
<ranges>
で定義されるコンセプトはイテレータを用いて定義されるものが多い。イテレータや番兵に関するコンセプトなどは引き続き<iterator>
で提供される。
また、Range対応版のアルゴリズム関数は引き続き<algorithm>
で提供される。
名前空間構造
<ranges>
で定義されるものは全てstd::ranges
名前空間の下にある。また、各種view
型を生成するRangeアダプタ/ファクトリオブジェクトはstd::ranges::views
名前空間の下で定義され、std::views
からもアクセスする事ができる。
名前空間だけを見てみると次のようになっている。
namespace std {
// 通常のstd名前空間
namespace ranges {
// <ranges>のものはここに定義される
namespace views {
// Rangeアダプタ/ファクトリオブジェクトが定義される
}
}
// この名前空間エイリアスによって、std::viewsとしてstd::ranges::viewsにアクセスできる
namespace views = ranges::views;
}
Rangeアクセス
これらの機能は従来<iterator>
でフリー関数として提供されていた。
C++20では関数によるカスタマイゼーションポイントの問題点を解消するため、関数オブジェクトとして再実装されている。
互換性を維持するために従来の関数も残っているが、これらのカスタマイゼーションポイントオブジェクトを使用することが推奨される。
名前 |
説明 |
対応バージョン |
begin |
Rangeの先頭を指すイテレータを取得する (customization point object) |
C++20 |
end |
Rangeの末尾の次を指すイテレータもしくは番兵を取得する (customization point object) |
C++20 |
cbegin |
Rangeの先頭を指す読み取り専用イテレータを取得する (customization point object) |
C++20 |
cend |
Rangeの末尾の次を指す読み取り専用イテレータもしくは番兵を取得する (customization point object) |
C++20 |
rbegin |
Rangeの末尾を指す逆イテレータを取得する (customization point object) |
C++20 |
rend |
Rangeの先頭の前を指す逆イテレータもしくは番兵を取得する (customization point object) |
C++20 |
crbegin |
Rangeの末尾を指す読み取り専用逆イテレータを取得する (customization point object) |
C++20 |
crend |
Rangeの先頭の前を指す読み取り専用逆イテレータもしくは番兵を取得する (customization point object) |
C++20 |
size |
Rangeの要素数を取得する (customization point object) |
C++20 |
ssize |
Rangeの要素数を、符号付き整数型で取得する (customization point object) |
C++20 |
empty |
Rangeが空かどうかを判定する (customization point object) |
C++20 |
data |
Rangeの要素配列へのポインタを取得する (customization point object) |
C++20 |
cdata |
Rangeの要素配列への読み取り専用ポインタを取得する (customization point object) |
C++20 |
Rangeに関連する型へのアクセス
Rangeコンセプト
カスタマイゼーションポイント
ビューインターフェース
名前 |
説明 |
対応バージョン |
view_base |
基底クラスとすることでview となるタグ型 (class) |
C++20 |
view_interface |
ビューの基底クラスとして推奨されるクラス (class template) |
C++20 |
部分Range
名前 |
説明 |
対応バージョン |
subrange_kind |
部分Rangeの種類を表す列挙体 (enum class) |
C++20 |
subrange |
イテレータペアをRangeとして扱う型 (class template) |
C++20 |
ダングリングイテレータハンドリング
名前 |
説明 |
対応バージョン |
dangling |
ダングリングイテレータ、ダングリングRangeを表す型 (class) |
C++20 |
borrowed_iterator_t |
Rangeがborrowed_range ではないときdangling となるイテレータ (alias template) |
C++20 |
borrowed_subrange_t |
Rangeがborrowed_range ではないときdangling となる部分Range (alias template) |
C++20 |
Rangeジェネレータ
名前 |
説明 |
対応バージョン |
elements_of |
子Range要素の生成を示すタグ型 (class template) |
C++23 |
Rangeファクトリ
Rangeファクトリは、Rangeではないオブジェクトからview
を生成するものである。
その実体は、引数の無いものは変数テンプレート、引数のあるものは関数テンプレートやカスタマイゼーションポイントオブジェクトとなっている。
empty view
名前 |
説明 |
対応バージョン |
empty_view |
空のRange (class template) |
C++20 |
views::empty |
empty_view を生成する (variable template) |
C++20 |
single view
名前 |
説明 |
対応バージョン |
single_view |
指定した値1つからなるRange (class template) |
C++20 |
views::single |
single_view を生成する (customization point object) |
C++20 |
iota view
名前 |
説明 |
対応バージョン |
iota_view |
単調増加列であるRange (class template) |
C++20 |
views::iota |
iota_view を生成する (customization point object) |
C++20 |
repeat view
名前 |
説明 |
対応バージョン |
repeat_view |
指定した値を指定回数繰り返すRange (class template) |
C++23 |
views::repeat |
repeat_view を生成する (customization point object) |
C++23 |
istream view
Rangeアダプタ
Rangeアダプタは、既存のRangeに作用して新たなRangeを生成するものである。
RangeアダプタをRangeに作用させる方法には、一部の例外を除き、関数記法とパイプライン記法の2つがある。
R
をRangeアダプタ、r
を元になるRangeとする。このとき、以下の2つの式は同じview
を生成する。
R(r) // 関数記法
r | R // パイプライン記法
Rangeアダプタを適用した結果はview
、すなわちRangeであることから、Rangeアダプタを次々と繋いでいくことができる。
R3(R2(R1(r))) // 関数記法
r | R1 | R2 | R3 // パイプライン記法
Rangeアダプタの処理は遅延評価され、要素は必要になるまで生成されない。このような仕組みは実際の仕事の多くをイテレータが担うことで実現している。
for (auto&& item : r | R) {
// ループ一回ごとに、(r | R)の要素を1つ生成する。このとき、rの要素を必要なだけ取得する。
}
Rangeアダプタオブジェクトは次のように定義される。
また、Rangeアダプタクロージャオブジェクトは次のように定義される。
Rangeアダプタオブジェクトadaptor
が2つ以上の引数をとる場合、以下の3つの式は等しい。
このとき、式adaptor(args...)
の値がRangeアダプタクロージャオブジェクトになっている。
なお、元となるRangeを複数とるRangeアダプタは、パイプライン記法を提供しない。
all view
名前 |
説明 |
対応バージョン |
ref_view |
Rangeへの参照として振る舞うビュー (class template) |
C++20 |
owning_view |
Rangeの右辺値をムーブして所有するビュー (class template) |
C++20 |
views::all |
Rangeへの参照として振る舞うビューを生成する (customization point object) |
C++20 |
views::all_t |
all の戻り値型 (alias template) |
C++20 |
as rvalue view
filter view
名前 |
説明 |
対応バージョン |
filter_view |
指定した条件を満たす要素だけを集めるビュー (class template) |
C++20 |
views::filter |
filter_view を生成する (customization point object) |
C++20 |
transform view
take view
名前 |
説明 |
対応バージョン |
take_view |
先頭から指定した個数だけ取り出すビュー (class template) |
C++20 |
views::take |
先頭から指定した個数だけ取り出すビューを生成する (customization point object) |
C++20 |
take while view
drop view
名前 |
説明 |
対応バージョン |
drop_view |
先頭から指定した個数だけ除外するビュー (class template) |
C++20 |
views::drop |
先頭から指定した個数だけ除外するビューを生成する (customization point object) |
C++20 |
drop while view
join view
名前 |
説明 |
対応バージョン |
join_view |
ネストされたRangeを平坦にするビュー (class template) |
C++20 |
views::join |
ネストされたRangeを平坦にするビューを生成する (customization point object) |
C++20 |
join with view
名前 |
説明 |
対応バージョン |
join_with_view |
ネストされたRangeをデリミタで区切りながら平坦にするビュー (class template) |
C++23 |
views::join_with |
ネストされたRangeをデリミタで区切りながら平坦にするビューを生成する (customization point object) |
C++23 |
lazy split view
split view
名前 |
説明 |
対応バージョン |
split_view |
文字列分割に特化したlazy_split_view (class template) |
C++20 |
views::split |
split_view を生成する (customization point object) |
C++20 |
concat view
名前 |
説明 |
対応バージョン |
concat_view |
複数のRangeを連結するビュー (class template) |
C++26 |
views::concat |
concat_view を生成する (customization point object) |
C++26 |
counted view
名前 |
説明 |
対応バージョン |
views::counted |
イテレータから指定した数の範囲をRangeとして扱うビューを生成する (customization point object) |
C++20 |
common view
名前 |
説明 |
対応バージョン |
common_view |
common_range にしたビュー (class template) |
C++20 |
views::common |
common_range なビューを生成する (customization point object) |
C++20 |
reverse view
as const view
elements view
名前 |
説明 |
対応バージョン |
elements_view |
タプルの第N要素にアクセスするビュー (class template) |
C++20 |
keys_view |
タプルの第0要素にアクセスするビュー (alias template) |
C++20 |
values_view |
タプルの第1要素にアクセスするビュー (alias template) |
C++20 |
views::elements |
elements_view を生成する (customization point object) |
C++20 |
views::keys |
keys_view を生成する (customization point object) |
C++20 |
views::values |
values_view を生成する (customization point object) |
C++20 |
enumerate view
zip view
名前 |
説明 |
対応バージョン |
zip_view |
複数のシーケンスから値を1つずつ取り出したtuple のビュー (class template) |
C++23 |
views::zip |
zip_view を生成する (customization point object) |
C++23 |
zip transform view
adjacent view
adjacent transform view
chunk view
名前 |
説明 |
対応バージョン |
chunk_view |
シーケンスを指定個数で区切ったview のシーケンス (class template) |
C++23 |
views::chunk |
chunk_view を生成する (customization point object) |
C++23 |
chunk by view
名前 |
説明 |
対応バージョン |
chunk_by_view |
2項述語が偽となる部分で区切ったview のシーケンス (class template) |
C++23 |
views::chunk_by |
chunk_by_view を生成する (customization point object) |
C++23 |
slide view
名前 |
説明 |
対応バージョン |
slide_view |
各要素とそれに隣接する要素を指定個数ずつ見るview のシーケンス (class template) |
C++23 |
views::slide |
slide_view を生成する (customization point object) |
C++23 |
stride view
名前 |
説明 |
対応バージョン |
stride_view |
要素を指定個数飛ばしに見るビュー (class template) |
C++23 |
views::stride |
stride_view を生成する (customization point object) |
C++23 |
cartesian product view
Range変換
名前 |
説明 |
対応バージョン |
to |
パイプライン記法でRangeからコンテナを構築する (class template) |
C++23 |
from_range_t |
Rangeからコンテナへの変換を示すタグ型 (class) |
C++23 |
from_range |
Rangeからコンテナへの変換を示すタグ値 (variable) |
C++23 |
実装例
バージョン
言語
処理系
関連項目
参照