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

履歴 編集

class template
<ranges>

# std::ranges::cartesian_product_view(C++23)

    namespace std::ranges {
      template<input_range First, forward_range... Vs>
        requires (view<First> && ... && view<Vs>)
      class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> { …… }; // (1)

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

## 概要

`cartesian_product_view`は複数のRangeの直積をとり、その要素を`tuple`として見せる`view`。

この`view`の要素数は、すべての指定したRangeの要素数の積である。

- (1): `cartesian_product_view`のクラス定義
- (2): `cartesian_product_view`を生成するカスタマイゼーションポイントオブジェクト(Rangeアダプタオブジェクトではない)

### Rangeコンセプト

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

- (1): すべてのRangeが`sized_range`のとき
- (2): すべてのRangeが`bidirectional_range`かつ、先頭以外のRangeがcartesian-product-common-argのとき
- (3): すべてのRangeが`random_access_range`かつ、先頭のRangeが`sized_range`のとき
- (4): 先頭のRangeがcartesian-product-common-argのとき

## 効果

- (2): 式`views::cartesian_product(Es...)`の効果は次の通り
  - `Es`が空でないとき、`cartesian_product_view<views::all_t<decltype((Es))>...>(Es...)` と等しい
  - `Es`が空のとき、`views::single(tuple())` と等しい

## 備考

本説明に用いる説明専用要素を以下のように定義する。

    namespace std::ranges {
      template<bool Const, class First, class... Vs>
      concept cartesian-product-is-random-access =          // exposition only
        (random_access_range<maybe-const<Const, First>> && ... &&
          (random_access_range<maybe-const<Const, Vs>>
            && sized_range<maybe-const<Const, Vs>>));

      template<class R>
      concept cartesian-product-common-arg =                // exposition only
        common_range<R> || (sized_range<R> && random_access_range<R>);

      template<bool Const, class First, class... Vs>
      concept cartesian-product-is-bidirectional =          // exposition only
        (bidirectional_range<maybe-const<Const, First>> && ... &&
          (bidirectional_range<maybe-const<Const, Vs>>
            && cartesian-product-common-arg<maybe-const<Const, Vs>>));

      template<class First, class... Vs>
      concept cartesian-product-is-common =                 // exposition only
        cartesian-product-common-arg<First>;

      template<class... Vs>
      concept cartesian-product-is-sized =                  // exposition only
        (sized_range<Vs> && ...);

      template<bool Const, template<class> class FirstSent, class First, class... Vs>
        concept cartesian-is-sized-sentinel =               // exposition only
          (sized_sentinel_for<FirstSent<maybe-const<Const, First>>,
              iterator_t<maybe-const<Const, First>>> && ...
            && (sized_range<maybe-const<Const, Vs>>
              && sized_sentinel_for<iterator_t<maybe-const<Const, Vs>>,
                  iterator_t<maybe-const<Const, Vs>>>));

      template<cartesian-product-common-arg R>
      constexpr auto cartesian-common-arg-end(R& r) {       // exposition only
        if constexpr (common_range<R>) {
          return ranges::end(r);
        } else {
          return ranges::begin(r) + ranges::distance(r);
        }
      }
    }

## メンバ関数

名前 | 説明 | 対応バージョン
--- | --- | ---
`(constructor)` | コンストラクタ | C++23
`begin` | 先頭を指すイテレータを取得する | C++23
`end` | 番兵を取得する | C++23
`size` | 要素数を取得する | C++23

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

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

## 推論補助

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

## 例

    #include <ranges>
    #include <vector>
    #include <list>
    #include <print>

    int main() {
      std::vector v = {1, 2};
      const std::list l = {'a', 'b', 'c'};

      std::println("{}", std::views::cartesian_product(v, l));

      // 空になる場合
      std::println("{}", std::views::cartesian_product());
    }

### 出力

    [(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b'), (2, 'c')]
    [()]

## バージョン

### 言語

- C++23

### 処理系

- Clang: 16.0 ✅
- GCC: 13.2 ✅
- Visual C++: 2022 Update 7 ✅

## 参照

- N4950 26 Ranges library