Skip to content

Latest commit

 

History

History
238 lines (196 loc) · 8 KB

generator.md

File metadata and controls

238 lines (196 loc) · 8 KB

generator

  • generator[meta header]
  • class template[meta id-type]
  • std[meta namespace]
  • cpp23[meta cpp]
namespace std {
  template<class Ref, class V = void, class Allocator = void>
  class generator : public ranges::view_interface<generator<Ref, V, Allocator>> {
    ...
  }
}
  • ranges::view_interface[link /reference/ranges/view_interface.md]

概要

generatorクラステンプレートは、コルーチンの評価により生成される要素列のビュー(view)を表現する。 特殊化されたgeneratorviewおよびinput_rangeのモデルである。

戻り値型generatorのコルーチン(以下、ジェネレータコルーチン)ではco_yield式を用いて値を生成する。co_yield std::ranges::elements_of(rng)式を用いると、ジェネレータコルーチンから入れ子Range(rng)の各要素を逐次生成する。 ジェネレータコルーチンではco_await式を利用できない。

ジェネレータコルーチンは遅延評価される。ジェネレータコルーチンが返すgeneratorオブジェクトの利用側(以下、呼び出し側)で先頭要素beginを指すイテレータを間接参照するまで、ジェネレータコルーチンの本体処理は実行されない。 呼び出し側がイテレータの間接参照を試みるとジェネレータコルーチンを再開(resume)し、ジェネレータコルーチン本体処理においてco_yield式に到達すると生成値を保持して再び中断(suspend)する。呼び出し側ではイテレータの間接参照の結果として生成値を取得する。

説明用メンバ

generatorでは下記の説明用メンバ型を定義する。

generatorおよびpromise_typeの動作説明のため、下記の説明用メンバを用いる。

適格要件

  • テンプレートパラメータAllocatorvoidではない場合、allocator_traits<Allocator>::pointerはポインタ型であること。
  • 説明用のメンバ型valueはCV修飾されないオブジェクト型であること。
  • 説明用のメンバ型referenceは参照型、またはcopy_constructibleのモデルであるCV修飾されないオブジェクト型であること。
  • 説明用のメンバ型referenceが参照型の場合にはRRef == remove_reference_t<reference>&&、それ以外の場合にはRRef == referenceとしたとき、それぞれ下記のモデルであること。

テンプレートパラメータAllocatorvoidではない場合、Cpp17Allocatorの要件を満たすこと。

メンバ関数

構築・破棄

名前 説明 対応バージョン
(constructor) コンストラクタ C++23
(destructor) デストラクタ C++23
operator=(generator other) noexcept; ムーブ代入演算子 C++23

イテレータ

名前 説明 対応バージョン
begin Viewの先頭を指すイテレータを取得する C++23
end Viewの番兵を取得する C++23

メンバ型

名前 説明 対応バージョン
yielded co_yield式の引数型(後述) C++23
promise_type ジェネレータコルーチンのPromise型 C++23
using yielded =
  conditional_t<is_reference_v<reference>, reference, const reference&>;
  • conditional_t[link /reference/type_traits/conditional.md]
  • is_reference_v[link /reference/type_traits/is_reference.md]

例1: 単一値の生成

#include <generator>
#include <ranges>
#include <iostream>

// 偶数値列を無限生成するコルーチン
std::generator<int> evens()
{
  int n = 0;
  while (true) {
    co_yield n;
    n += 2;
  }
}

int main()
{
  // ジェネレータにより生成されるレンジのうち
  // 先頭から5個までの要素値を列挙する
  for (int n : evens() | std::views::take(5)) {
    std::cout << n << std::endl;
  }
}
  • std::generator[color ff0000]
  • co_yield[link /lang/cpp20/coroutines.md]
  • std::views::take[link /reference/ranges/take_view.md]

出力

0
2
4
6
8

例2: レンジ要素値の逐次生成

#include <generator>
#include <iostream>
#include <list>
#include <ranges>
#include <vector>

// レンジの要素値を逐次生成するコルーチン
std::generator<int> ints()
{
  int arr[] = {1, 2, 3};
  co_yield std::ranges::elements_of(arr);
  std::vector<int> vec = {4, 5, 6};
  co_yield std::ranges::elements_of(vec);
  std::list<int> lst = {7, 8, 9};
  co_yield std::ranges::elements_of(lst);
}

int main()
{
  for (int n : ints())) {
    std::cout << n << ' ';
  }
}
  • std::generator[color ff0000]
  • co_yield[link /lang/cpp20/coroutines.md]
  • std::ranges::elements_of[link /reference/ranges/elements_of.md]

出力

1 2 3 4 5 6 7 8 9 

例3: ジェネレータのネスト

#include <generator>
#include <iostream>
#include <ranges>
#include <memory>

// 二分木ノード
struct node {
  int value;
  std::unique_ptr<node> left = nullptr;
  std::unique_ptr<node> right = nullptr;
};

// 二分木を幅優先走査: 左(left)→自ノード→右(right)
std::generator<int> traverse(const node& e)
{
  if (e.left) {
    co_yield std::ranges::elements_of(traverse(*e.left));
  }
  co_yield e.value;
  if (e.right) {
    co_yield std::ranges::elements_of(traverse(*e.right));
  }
}

int main()
{
  // tree:
  //    2
  //   / ¥
  //  1   4
  //     / ¥
  //    3   5
  node tree = {
    2,
    std::make_unique<node>(1),
    std::make_unique<node>(
      4,
      std::make_unique<node>(3),
      std::make_unique<node>(5)
    ),
  };

  for (int n: traverse(tree)) {
    std::cout << n << std::endl;
  }
}
  • std::generator[color ff0000]
  • co_yield[link /lang/cpp20/coroutines.md]
  • std::ranges::elements_of[link /reference/ranges/elements_of.md]
  • std::make_unique[link /reference/memory/make_unique.md]

出力

1
2
3
4
5

バージョン

言語

  • C++23

処理系

関連項目

参照