最終更新日時: 2026年05月21日 15時03分06秒 (JST)
Akira Takahashi が更新

履歴 編集

class template
<ranges>

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

    namespace std::ranges {
      template<view V>
        requires (!common_range<V> && copyable<iterator_t<V>>)
      class common_view : public view_interface<common_view<V>> { …… }; // (1)

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

## 概要

- (1): 任意のRangeを`common_range`にする`view`
- (2): `common_view`または同じ効果を実現する`view`を生成するRangeアダプタオブジェクト

イテレータと番兵の型が同じである必要があるレガシーなアルゴリズム関数に対して、イテレータと番兵が異なるRangeを渡したい場合 (たとえば`iota_view`)、このビューで`common_range`に変換することで、同じ型のイテレータペアを取得できるようになる。

### Rangeコンセプト

borrowed | sized | output | input | forward | bidirectional | random_access | contiguous | common | viewable | view
--- | --- | --- | --- | --- | --- | --- | --- | --- | --- | ---
※ | ※ | ※ | ※ | ※ | ※ | ※ | ※ | ○ | ○ | ○

※ 参照先のRangeに従う

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

- `view<V>`
- `!common_range<V>`
- `copyable<iterator_t<V>>`

## 効果

- (2): 式`views::common(E)`の効果は次の通り
  - `decltype((E))`が`common_range`のモデルであり、`views::all(E)`が有効な式であれば、`views::all(E)`と等しい
  - それ以外のとき、`common_view{E}`と等しい

## メンバ関数

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

`r`を参照先のRangeとする。`size`は、`ranges::size(r)`が有効な式であるときに定義される。

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

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

## 推論補助

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

## 例

    #include <ranges>
    #include <concepts>
    #include <string_view>

    int main() {
      using namespace std;

      // 無限長のiotaはcommon_rangeではない
      static_assert(!ranges::common_range<decltype(views::iota(0))>);
      // commonを適用するとcommon_rangeになる
      static_assert(ranges::common_range<decltype(views::iota(0) | views::common)>);

      // 元からcommon_rangeなviewに適用しても型は変わらない
      static_assert(same_as<decltype(string_view{} | views::common), string_view>);
    }

### 出力

## 実装例

    namespace std::ranges {
      template<view V>
        requires (!common_range<V> && copyable<iterator_t<V>>)
      class common_view : public view_interface<common_view<V>> {
      private:
        V base_ = V();
      public:
        common_view() requires default_initializable<V> = default;

        constexpr explicit common_view(V r) : base_(std::move(r)) {}

        constexpr V base() const & requires copy_constructible<V> { return base_; }
        constexpr V base() && { return std::move(base_); }

        constexpr auto begin() {
          if constexpr (random_access_range<V> && sized_range<V>)
            return ranges::begin(base_);
          else
            return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::begin(base_));
        }

        constexpr auto begin() const requires range<const V> {
          if constexpr (random_access_range<const V> && sized_range<const V>)
            return ranges::begin(base_);
          else
            return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::begin(base_));
        }

        constexpr auto end() {
          if constexpr (random_access_range<V> && sized_range<V>)
            return ranges::begin(base_) + ranges::size(base_);
          else
            return common_iterator<iterator_t<V>, sentinel_t<V>>(ranges::end(base_));
        }

        constexpr auto end() const requires range<const V> {
          if constexpr (random_access_range<const V> && sized_range<const V>)
            return ranges::begin(base_) + ranges::size(base_);
          else
            return common_iterator<iterator_t<const V>, sentinel_t<const V>>(ranges::end(base_));
        }

        constexpr auto size() requires sized_range<V> {
          return ranges::size(base_);
        }
        constexpr auto size() const requires sized_range<const V> {
          return ranges::size(base_);
        }
      };

      template<class R>
      common_view(R&&) -> common_view<views::all_t<R>>;
    }

## バージョン

### 言語

- C++20

### 処理系

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

## 関連項目

- C++17 範囲 for ループの制限緩和
  範囲for文は、C++17の時点で先行して`common_range`ではない範囲を扱えるようになっている。

## 参照

- N4861 24 Ranges library
- C++20 ranges
- P2017R1 Conditionally borrowed ranges