最終更新日時: 2025年07月09日 00時33分39秒 (JST)
Akira Takahashi が更新

履歴 編集

type-alias
<iterator>

# std::projected(C++20)

    namespace std {
      // (1) C++20の定義
      template <indirectly_readable I, indirectly_regular_unary_invocable<I> Proj>
      struct projected {
        using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>;

        indirect_result_t<Proj&, I> operator*() const;  // 宣言のみ
      };
      // incrementable_traitsにアダプトする
      template <weakly_incrementable I, class Proj>
      struct incrementable_traits<projected<I, Proj>> {
        using difference_type = iter_difference_t<I>;
      };

      // (1) C++26の定義
      template <class I, class Proj>
      struct projected-impl { // 説明用の型
        struct type { // 説明用の型
          using value_type = remove_cvref_t<indirect_result_t<Proj&, I>>;
          using difference_type = iter_difference_t<I>; // weakly_incrementableをモデル化する場合にのみ存在する
          indirect_result_t<Proj&, I> operator*() const; // 宣言のみで定義なし
        };
      };
      template <indirectly_readable I, indirectly_regular_unary_invocable<I> Proj>
      using projected = projected-impl<I, Proj>::type;
    }

## 概要

間接参照可能な型`I`に任意の射影操作`Proj`を適用した結果を表す`indirectly_readable`のモデルとなる型を生成する。

これは射影操作を受け取るコンセプトやアルゴリズムを制約するために使用するものであり、評価される文脈で使用可能ではない。主に、射影操作の結果に対してイテレータ関連のコンセプトを適用する場合に使用する（射影の結果を再び`indirectly_readable`な型に写す事で、一部のイテレータに対するコンセプトを使いまわす事が出来る）。

## 備考

- C++26:
  - C++20の`projected`の定義では、ADLによって不完全型に完全な定義を要求してしまっており、以下のようなコードがコンパイルエラーになっていたが、C++26での定義変更によって不完全型が許容されるようになった。

        Holder<Incomplete> *a[10] = {};
        std::ranges::count(a, a + 10, nullptr); // コンパイルエラー

## 例

    #include <iterator>
    #include <vector>

    int main() {
      using vec_iterator = std::vector<int>::iterator;
      using vecitr_proj = std::projected<vec_iterator, std::identity>;

      static_assert(std::indirectly_readable<vecitr_proj>);
      static_assert(std::same_as<vecitr_proj::value_type                  , int>);
      static_assert(std::same_as<std::iter_difference_t<vecitr_proj>      , std::ptrdiff_t>);
      static_assert(std::same_as<std::iter_value_t<vecitr_proj>           , int>);
      static_assert(std::same_as<std::iter_reference_t<vecitr_proj>       , int&>);
      static_assert(std::same_as<std::iter_rvalue_reference_t<vecitr_proj>, int&&>);
      static_assert(std::same_as<std::iter_common_reference_t<vecitr_proj>, int&>);

      //別の射影でプロジェクション
      using vecitr_proj2 = std::projected<vec_iterator, decltype([](int) -> double { return 0.0;})>;

      static_assert(std::indirectly_readable<vecitr_proj2>);
      static_assert(std::same_as<vecitr_proj2::value_type                  , double>);
      static_assert(std::same_as<std::iter_difference_t<vecitr_proj2>      , std::ptrdiff_t>);
      static_assert(std::same_as<std::iter_value_t<vecitr_proj2>           , double>);
      static_assert(std::same_as<std::iter_reference_t<vecitr_proj2>       , double>);
      static_assert(std::same_as<std::iter_rvalue_reference_t<vecitr_proj2>, double>);
      static_assert(std::same_as<std::iter_common_reference_t<vecitr_proj2>, double>);
    }

### 出力

## バージョン

### 言語

- C++20

### 処理系

- Clang: ??
- GCC: 10.1 ✅
- Visual C++: 2019 Update 6 ✅

## 関連項目

- `projected_value_t`
- `indirectly_comparable`
- `mergeable`
- `sortable`

## 参照

- P0896R4 The One Ranges Proposal (was Merging the Ranges TS)
- P2538R1 ADL-proof `std::projected`