- 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)を表現する。
特殊化されたgenerator
はview
およびinput_range
のモデルである。
戻り値型generator
のコルーチン(以下、ジェネレータコルーチン)ではco_yield
式を用いて値を生成する。co_yield
std::ranges::elements_of
(rng)
式を用いると、ジェネレータコルーチンから入れ子Range(rng
)の各要素を逐次生成する。
ジェネレータコルーチンではco_await
式を利用できない。
ジェネレータコルーチンは遅延評価される。ジェネレータコルーチンが返すgenerator
オブジェクトの利用側(以下、呼び出し側)で先頭要素begin
を指すイテレータを間接参照するまで、ジェネレータコルーチンの本体処理は実行されない。
呼び出し側がイテレータの間接参照を試みるとジェネレータコルーチンを再開(resume)し、ジェネレータコルーチン本体処理においてco_yield
式に到達すると生成値を保持して再び中断(suspend)する。呼び出し側ではイテレータの間接参照の結果として生成値を取得する。
generator
では下記の説明用メンバ型を定義する。
value
:conditional_t
<
is_void_v
<V>,
remove_cvref_t
<Ref>, V>
reference
:conditional_t
<
is_void_v
<V>, Ref&&, Ref>
iterator
: ジェネレータが返すイテレータ型。
generator
およびpromise_type
の動作説明のため、下記の説明用メンバを用いる。
coroutine_handle
<
promise_type
>
: コルーチンハンドル(coroutine_
)unique_ptr
<
stack
<
coroutine_handle<>
>>
: アクティブスタック(active_
)
- テンプレートパラメータ
Allocator
がvoid
ではない場合、allocator_traits
<Allocator>::pointer
はポインタ型であること。 - 説明用のメンバ型
value
はCV修飾されないオブジェクト型であること。 - 説明用のメンバ型
reference
は参照型、またはcopy_constructible
のモデルであるCV修飾されないオブジェクト型であること。 - 説明用のメンバ型
reference
が参照型の場合にはRRef
==remove_reference_t
<reference>&&
、それ以外の場合にはRRef
==reference
としたとき、それぞれ下記のモデルであること。common_reference_with
<reference&&, value&>
common_reference_with
<reference&&, RRef&&>
common_reference_with
<RRef&&, const value&>
テンプレートパラメータAllocator
がvoid
ではない場合、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]
#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
#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
#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
- Clang:
- GCC:
- ICC:
- Visual C++: