最終更新日時: 2025年10月17日 18時16分31秒 (JST)
Raclamusi が更新

履歴 編集

class template
<ranges>

# std::ranges::lazy_split_view(C++20)

    namespace std::ranges {

      template<input_range V, forward_range Pattern>
        requires view<V> && view<Pattern> &&
                 indirectly_comparable<iterator_t<V>, iterator_t<Pattern>, ranges::equal_to> &&
                 (forward_range<V> || tiny-range<Pattern>)
      class lazy_split_view : public view_interface<lazy_split_view<V, Pattern>> { …… };   // (1)

      namespace views {
        inline constexpr /*unspecified*/ lazy_split = /*unspecified*/;                     // (2)
      }
    }

## 概要

- (1): `input_range`を要素、または要素の`view`からなるパターンをデリミタとして分割し、それぞれの部分Rangeを要素とする新たなRangeとして扱う`view`
- (2): `lazy_split_view`を生成するRangeアダプタオブジェクト

### Rangeコンセプト

borrowed | sized | output | input | forward | bidirectional | random_access | contiguous | common | viewable | view
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
|  |  | ○ | (1) |  |  |  | (2) | ○ | ○

- (1): `V`が`forward_range`のとき
- (2): `V`が`forward_range`かつ`common_range`のとき

### Rangeコンセプト (各部分Range)

borrowed | sized | output | input | forward | bidirectional | random_access | contiguous | common | viewable | view
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
|  |  | ○ | (1) |  |  |  |  | ○ | ○

- (1): `V`が`forward_range`のとき

## テンプレートパラメータ制約

説明専用コンセプト`tiny-range`を次のように定義する。

    template<auto> struct require-constant;

    template<class R>
    concept tiny-range = sized_range<R> &&
      requires { typename require-constant<remove_reference_t<R>::size()>; } && (remove_reference_t<R>::size() <= 1);

これを用いて、

- `view<V>` かつ `input_range<V>`
- `view<Pattern>` かつ `forward_range<Pattern>`
- `V`のイテレータと`Pattern`のイテレータが等値比較可能である
- `forward_range<V>` または `tiny-range<Pattern>`

## 効果

- (2): 式`views::lazy_split(E, F)`の効果は`lazy_split_view{E, F}`と等しい。

## メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++20
`base` | `V`の参照を取得する | C++20
`begin` | 先頭を指すイテレータを取得する | C++20
`end` | 番兵を取得する | C++20

## 継承しているメンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`empty` | Rangeが空かどうかを判定する | C++20
`operator bool` | Rangeが空でないかどうかを判定する | C++20
`front` | 先頭要素への参照を取得する | C++20
`back` | 末尾要素への参照を取得する | C++20
`cbegin` | 定数イテレータを取得する | C++23
`cend` | 定数イテレータ（番兵）を取得する | C++23

## 推論補助

名前 | 説明 | 対応バージョン
--- | --- | ---
`(deduction_guide)` | クラステンプレートの推論補助 | C++20

## 例

### `range`による`range`の分割

    #include <ranges>
    #include <vector>
    #include <iostream>

    int main() {
      using namespace std;
      std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9};
      std::vector<int> pattern = {4, 5};

      for (auto inner_range : v | views::lazy_split(pattern)) {
        for (int n : inner_range) {
          std::cout << n;
        }
        std::cout << '\n';
      }
    }

### 出力

    123
    6789

### `input_range`の分割

この場合はデリミタは1要素でなければならず、`range`による分割はできない。

    #include <ranges>
    #include <vector>
    #include <iostream>
    #include <sstream>

    int main() {
      using namespace std;
      auto iss = istringstream{"1 2 3 1 4 5 6 1 7 8 1 9 1"};

      for (auto inner_range : views::istream<int>(iss) | views::lazy_split(1)) {
        for (int n : inner_range) {
          std::cout << n;
        }
        std::cout << '\n';
      }
    }

### 出力

    23
    456
    78
    9

## バージョン

### 言語

- C++20

### 処理系

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

## 参照

- P2210R2 Superior String Splitting
- N4861 24 Ranges library
- C++20 ranges