最終更新日時: 2026年06月21日 16時47分35秒 (JST)
Raclamusi が更新

履歴 編集

<ranges>

# ranges(C++20)

`<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
`reserve_hint` | Rangeの要素数の近似値を取得する (customization point object) | C++26
`empty` | Rangeが空かどうかを判定する (customization point object) | C++20
`data` | Rangeの要素配列へのポインタを取得する (customization point object) | C++20
`cdata` | Rangeの要素配列への読み取り専用ポインタを取得する (customization point object) | C++20

## Rangeに関連する型へのアクセス

名前 | 説明 | 対応バージョン
--- | --- | ---
`iterator_t` | イテレータ型を取得する (alias template) | C++20
`sentinel_t` | 番兵型を取得する (alias template) | C++20
`const_iterator_t` | 定数イテレータ型を取得する (alias template) | C++23
`const_sentinel_t` | 定数番兵型を取得する (alias template) | C++23
`range_difference_t` | イテレータの差の型を取得する (alias template) | C++20
`range_size_t` | サイズの型を取得する(alias template) | C++20
`range_value_t` | 要素の型を取得する (alias template) | C++20
`range_reference_t` | 要素の参照型を取得する (alias template) | C++20
`range_const_reference_t` | 要素の定数参照型を取得する (alias template) | C++23
`range_rvalue_reference_t` | 要素の右辺値参照型を取得する (alias template) | C++20

## Rangeコンセプト

名前 | 説明 | 対応バージョン
--- | --- | ---
`range` | Rangeを定義するコンセプト (concept) | C++20
`borrowed_range` | 所有権を持たないRange (concept) | C++20
`sized_range` | サイズを償却定数時間で求められるRange (concept) | C++20
`approximately_sized_range` | サイズの近似値を償却定数時間で求められるRange (concept) | C++26
`view` | ビューであるRange (concept) | C++20
`output_range` | イテレータが出力イテレータであるRange (concept) | C++20
`input_range` | イテレータが入力イテレータであるRange (concept) | C++20
`forward_range` | イテレータが前進イテレータであるRange (concept) | C++20
`bidirectional_range` | イテレータが双方向イテレータであるRange (concept) | C++20
`random_access_range` | イテレータがランダムアクセスイテレータであるRange (concept) | C++20
`contiguous_range` | イテレータが隣接イテレータであるRange (concept) | C++20
`common_range` | イテレータと番兵の型が等しいRange (concept) | C++20
`viewable_range` | ビューに変換できるRange (concept) | C++20
`constant_range` | 要素が定数なRange (concept) | C++23
`sized-random-access-range` | サイズ付きランダムアクセスRange (説明専用concept) | C++26

## カスタマイゼーションポイント

名前 | 説明 | 対応バージョン
--- | --- | ---
`enable_borrowed_range` | Rangeを`borrowed_range`にする (variable template) | C++20
`enable_view` | Rangeを`view`にする (variable template) | C++20
`disable_sized_range` | Rangeを`sized_range`にならないようにする (variable template) | C++20

## ビューインターフェース

名前 | 説明 | 対応バージョン
--- | --- | ---
`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
`views::indices` | 0から始まる整数列のRangeを生成する (customization point object) | C++26

### repeat view

名前 | 説明 | 対応バージョン
--- | --- | ---
`repeat_view` | 指定した値を指定回数繰り返すRange (class template) | C++23
`views::repeat` | `repeat_view`を生成する (customization point object) | C++23

### istream view

名前 | 説明 | 対応バージョン
--- | --- | ---
`basic_istream_view` | 入力ストリームから値を読むRange (class template) | C++20
`istream_view` | 入力ストリームから値を読むRange (alias template) | C++20
`wistream_view` | 入力ストリームから値を読むRange (alias template) | C++20
`views::istream` | `basic_istream_view`を生成する (customization point object) | C++20

## 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アダプタオブジェクトは次のように定義される。

- 第1引数に`viewable_range`を受け取って`view`を返すカスタマイゼーションポイントオブジェクト

また、Rangeアダプタクロージャオブジェクトは次のように定義される。

- (C++20) `viewable_range`を受け取って`view`を返す単項関数オブジェクト
- (C++23) Rangeを受け取る単項関数オブジェクト

Rangeアダプタオブジェクト`adaptor`が2つ以上の引数をとる場合、以下の3つの式は等しい。

    adaptor(range, args...)
    adaptor(args...)(range)
    range | adaptor(args...)

このとき、式`adaptor(args...)`の値がRangeアダプタクロージャオブジェクトになっている。

なお、元となるRangeを複数とるRangeアダプタは、パイプライン記法を提供しない。

名前 | 説明 | 対応バージョン
--- | --- | ---
`range_adaptor_closure` | Rangeアダプタクロージャオブジェクトの基底クラス (class template) | C++23

### 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

名前 | 説明 | 対応バージョン
--- | --- | ---
`as_rvalue_view` | 各要素をrvalueにするビュー (class template) | C++23
`views::as_rvalue` | `as_rvalue_view`を生成する (customization point object) | C++23

### filter view

名前 | 説明 | 対応バージョン
--- | --- | ---
`filter_view` | 指定した条件を満たす要素だけを集めるビュー (class template) | C++20
`views::filter` | `filter_view`を生成する (customization point object) | C++20

### transform view

名前 | 説明 | 対応バージョン
--- | --- | ---
`transform_view` | 指定した関数で各要素を変換するビュー (class template) | C++20
`views::transform` | `transform_view`を生成する (customization point object) | C++20

### take view

名前 | 説明 | 対応バージョン
--- | --- | ---
`take_view` | 先頭から指定した個数だけ取り出すビュー (class template) | C++20
`views::take` | 先頭から指定した個数だけ取り出すビューを生成する (customization point object) | C++20

### take while view

名前 | 説明 | 対応バージョン
--- | --- | ---
`take_while_view` | 先頭から指定した条件を満たす範囲を取り出すビュー (class template) | C++20
`views::take_while` | `take_while_view`を生成する (customization point object) | C++20

### drop view

名前 | 説明 | 対応バージョン
--- | --- | ---
`drop_view` | 先頭から指定した個数だけ除外するビュー (class template) | C++20
`views::drop` | 先頭から指定した個数だけ除外するビューを生成する (customization point object) | C++20

### drop while view

名前 | 説明 | 対応バージョン
--- | --- | ---
`drop_while_view` | 先頭から指定した条件を満たす範囲を除外するビュー (class template) | C++20
`views::drop_while` | `drop_while_view`を生成する (customization point object) | C++20

### 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

名前 | 説明 | 対応バージョン
--- | --- | ---
`lazy_split_view` | Rangeを指定したデリミタで分割するビュー (class template) | C++20
`views::lazy_split` | `lazy_split_view`を生成する (customization point object) | C++20

### 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

名前 | 説明 | 対応バージョン
--- | --- | ---
`reverse_view` | 逆順のビュー (class template) | C++20
`views::reverse` | 逆順のビューを生成する (customization point object) | C++20

### as const view

名前 | 説明 | 対応バージョン
--- | --- | ---
`as_const_view` | 各要素をconstにするビュー (class template) | C++23
`views::as_const` | `as_const_view`を生成する (customization point object) | C++23

### 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

名前 | 説明 | 対応バージョン
--- | --- | ---
`enumerate_view` | シーケンスにインデックスを付ける`view` (class template) | C++23
`views::enumerate` | `enumerate_view`を生成する (customization point object) | C++23

### zip view

名前 | 説明 | 対応バージョン
--- | --- | ---
`zip_view` | 複数のシーケンスから値を1つずつ取り出した`tuple`のビュー (class template) | C++23
`views::zip` | `zip_view`を生成する (customization point object) | C++23

### zip transform view

名前 | 説明 | 対応バージョン
--- | --- | ---
`zip_transform_view` | 複数のシーケンスから値を1つずつ取り出し、関数を適用した結果のビュー (class template) | C++23
`views::zip_transform` | `zip_transform_view`を生成する (customization point object) | C++23

### adjacent view

名前 | 説明 | 対応バージョン
--- | --- | ---
`adjacent_view` | 各要素とそれに隣接する要素を指定個数ずつ取り出した`tuple`のビュー (class template) | C++23
`views::adjacent` | `adjacent_view`を生成する (variable template) | C++23
`views::pairwise` | `adjacent<2>`の別名 (customization point object) | C++23

### adjacent transform view

名前 | 説明 | 対応バージョン
--- | --- | ---
`adjacent_transform_view` | `adjacent_view`と同様に取り出し、関数を適用した結果のビュー (class template) | C++23
`views::adjacent_transform` | `adjacent_transform_view`を生成する (customization point object) | C++23

### 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

名前 | 説明 | 対応バージョン
--- | --- | ---
`cartesian_product_view` | シーケンスの直積集合のビュー (class template) | C++23
`views::cartesian_product` | `cartesian_product_view`を生成する (customization point object) | C++23

### to input view

名前 | 説明 | 対応バージョン
--- | --- | ---
`as_input_view` | 入力用Rangeに変換する (class template) | C++26
`views::as_input` | `as_input_view`を生成する (customization point object) | C++26

### cache latest view

名前 | 説明 | 対応バージョン
--- | --- | ---
`cache_latest_view` | 最後にアクセスした要素をキャッシュするビュー (class template) | C++26
`views::cache_latest` | `cache_latest_view`を生成する (customization point object) | C++26

## Range変換

名前 | 説明 | 対応バージョン
--- | --- | ---
`to` | パイプライン記法でRangeからコンテナを構築する (class template) | C++23
`from_range_t` | Rangeからコンテナへの変換を示すタグ型 (class) | C++23
`from_range` | Rangeからコンテナへの変換を示すタグ値 (variable) | C++23

## 実装例

- libstdc++
- libc++
- MSVC

## バージョン

### 言語

- C++20

### 処理系

- Clang: 13.0.0 ✅
- GCC: 10.1.0 ✅
- ICC: ?
- Visual C++: 2019 Update 10 ✅

## 関連項目

- `<iterator>`
- `<concepts>`
- `<algorithm>`

## 参照

- N4861 24 Ranges library
- N4950 26 Ranges library
- C++20 ranges
- P2278R4 `cbegin` should always return a constant iterator