Difference between revisions of "cpp/coroutine/generator"
m (→Member types: reorder.) |
(→Example: a data structure iteration I think is a compelling demo of the utility of generator, especially a recursive data structure) |
||
Line 96: | Line 96: | ||
#include <generator> | #include <generator> | ||
#include <iostream> | #include <iostream> | ||
− | |||
− | + | template<typename T> | |
+ | struct Tree | ||
{ | { | ||
− | for (; | + | T value; |
− | } | + | Tree *left{}, *right{}; |
+ | |||
+ | std::generator<const T&> traverse_preorder() const | ||
+ | { | ||
+ | if (left) | ||
+ | for (const T& x : left->traverse_preorder()) | ||
+ | co_yield x; | ||
+ | |||
+ | co_yield value; | ||
+ | if (right) | ||
+ | for (const T& x : right->traverse_preorder()) | ||
+ | co_yield x; | ||
+ | } | ||
+ | }; | ||
+ | |||
int main() | int main() | ||
{ | { | ||
− | + | Tree<int> tree[] | |
− | std::cout << | + | { |
+ | {0}, {2}, {4}, {6}, | ||
+ | {1, tree + 0, tree + 1}, {5, tree + 2, tree + 3}, | ||
+ | {3, tree + 4, tree + 5} | ||
+ | }; | ||
+ | |||
+ | for (int x : tree[6].traverse_preorder()) | ||
+ | std::cout << x << ' '; | ||
+ | |||
std::cout << '\n'; | std::cout << '\n'; | ||
} | } | ||
|output= | |output= | ||
− | + | 0 1 2 3 4 5 6 | |
}} | }} | ||
Revision as of 09:59, 20 January 2024
Defined in header <generator>
|
||
template< class Ref, |
(1) | (since C++23) |
namespace pmr { template< class Ref, class V = void > |
(2) | (since C++23) |
std::generator
presents a view
of the elements yielded by the evaluation of a coroutine.A std::generator
generates a sequence of elements by repeatedly resuming the coroutine from which it was returned.
Each time a co_yield statement is evaluated, the coroutine produces one element of the sequence.
When the co_yield statement is of the form co_yield ranges::elements_of(rng), each element of the range
rng is successively produced as an element of the sequence.
std::generator
models view
and input_range
.
The behavior of a program that adds a specialization for std::generator
is undefined.
Contents |
Data members
Name | Description |
active_ (private)
|
Internally, each active instance of
|
coroutine_ (private)
|
std::coroutine_handle<promise_type> (exposition-only member object*) |
Template parameters
Ref | - | the reference type (ranges::range_reference_t) of the generator. If V is void, both the reference type and the value type are inferred from Ref
|
V | - | the value type (range_value_t ) of the generator, or void
|
Allocator | - | an allocator type or void |
If Allocator
is not void, then:
- std::allocator_traits<Allocator>::pointer is a pointer type;
-
Allocator
meets the Allocator requirements.
Member types
Member type | Definition |
value (private)
|
std::conditional_t<std::is_void_v<V>, std::remove_cvref_t<Ref>, V>;.value is a cv-unqualified object type.(exposition-only member type*) |
reference (private)
|
std::conditional_t<std::is_void_v<V>, Ref&&, Ref>;.reference is either a reference type, or a cv-unqualified object type that models copy_constructible .(exposition-only member type*) |
yielded
|
std::conditional_t<std::is_reference_v<reference>, reference, const reference&>. |
Let /*RRef*/ denote:
- std::remove_reference_t</*reference*/>&&, if /*reference*/ is a reference type, and
- /*reference*/ otherwise.
The following concepts are modeled:
- std::common_reference_with</*reference*/&&, /*value*/&>,
- std::common_reference_with</*reference*/&&, /*RRef*/&&>, and
- std::common_reference_with</*RRef*/&&, const /*value*/&>.
Member functions
constructs a generator object (public member function) | |
effectively destroys the entire stack of yielded generator s (public member function) | |
assigns a generator object (public member function) | |
resumes the initially suspended coroutine and returns an iterator to its handle (public member function) | |
returns std::default_sentinel (public member function) | |
Inherited from std::ranges::view_interface | |
returns whether the derived view is empty. Provided if it satisfies sized_range or forward_range . (public member function of std::ranges::view_interface<D> )
| |
(C++23) |
returns a constant iterator to the beginning of the range. (public member function of std::ranges::view_interface<D> )
|
(C++23) |
returns a sentinel for the constant iterator of the range. (public member function of std::ranges::view_interface<D> )
|
returns whether the derived view is not empty. Provided if ranges::empty is applicable to it. (public member function of std::ranges::view_interface<D> )
|
Nested classes
the promise type (public member class) | |
the iterator type (exposition-only member class*) |
Notes
Feature-test macro | Value | Std | Feature |
---|---|---|---|
__cpp_lib_generator |
202207L | (C++23) | std::generator – synchronous coroutine generator for ranges
|
Example
#include <generator> #include <iostream> template<typename T> struct Tree { T value; Tree *left{}, *right{}; std::generator<const T&> traverse_preorder() const { if (left) for (const T& x : left->traverse_preorder()) co_yield x; co_yield value; if (right) for (const T& x : right->traverse_preorder()) co_yield x; } }; int main() { Tree<int> tree[] { {0}, {2}, {4}, {6}, {1, tree + 0, tree + 1}, {5, tree + 2, tree + 3}, {3, tree + 4, tree + 5} }; for (int x : tree[6].traverse_preorder()) std::cout << x << ' '; std::cout << '\n'; }
Output:
0 1 2 3 4 5 6
References
- C++23 standard (ISO/IEC 14882:2024):
- 26.8 Range generators [coro.generator]
See also
(C++20) |
creates a coroutine handle that has no observable effects when resumed or destroyed (function) |