Difference between revisions of "cpp/coroutine/generator"
D41D8CD98F (Talk | contribs) (use {{void}}) |
D41D8CD98F (Talk | contribs) (the reference implementation (https://godbolt.org/z/5hcaPcfvP) doesn't really use a std::stack. Describe the stack in a different way) |
||
Line 31: | Line 31: | ||
The behavior of a program that adds a specialization for {{ttt|std::generator}} is undefined. <!--[coro.generator.class.4] 0_o --> | The behavior of a program that adds a specialization for {{ttt|std::generator}} is undefined. <!--[coro.generator.class.4] 0_o --> | ||
+ | |||
+ | Internally, each active instance of {{tt|std::generator}} is associated with a stack. | ||
+ | |||
+ | * When {{rlt|begin}} is called, a new stack is created and the generator is added to the stack. | ||
+ | * When {{c|co_yield ranges::elements_of(rng)}} is evaluated in a generator body, {{c|rng}} is converted to a generator and added to the stack that contains the enclosing generator. | ||
+ | * When a generator iterator is {{rl|iterator#increment|incremented}}, the coroutine at the top of the associated stack is resumed. | ||
+ | * When a generator finishes (i.e. when {{rlt|promise_type/final_suspend|final_suspend}} is called), it is removed from the stack. | ||
===Template parameters=== | ===Template parameters=== | ||
Line 42: | Line 49: | ||
* {{c|std::allocator_traits<Allocator>::pointer}} is a pointer type; | * {{c|std::allocator_traits<Allocator>::pointer}} is a pointer type; | ||
* {{tt|Allocator}} meets the {{named req|LegacyAllocator}} requirements. | * {{tt|Allocator}} meets the {{named req|LegacyAllocator}} requirements. | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
===Member types=== | ===Member types=== |
Revision as of 10:18, 15 February 2023
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.
Specializations of std::generator
should model view
and input_range
.
The behavior of a program that adds a specialization for std::generator
is undefined.
Internally, each active instance of std::generator
is associated with a stack.
- When
begin
is called, a new stack is created and the generator is added to the stack. - When co_yield ranges::elements_of(rng) is evaluated in a generator body, rng is converted to a generator and added to the stack that contains the enclosing generator.
- When a generator iterator is incremented, the coroutine at the top of the associated stack is resumed.
- When a generator finishes (i.e. when
final_suspend
is called), it is removed from the stack.
Contents |
Template parameters
Ref | - | a reference type |
V | - | a value type 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 LegacyAllocator requirements.
Member types
Member type | Definition |
yielded (since C++23)
|
std::conditional_t<std::is_reference_v<T>, T, const T&> |
/*value*/ (private)(since C++23) | std::conditional_t<std::is_void_v<V>, std::remove_cvref_t<Ref>, V>;. /*value*/ is a cv-unqualified object type. The name is for exposition only. |
/*reference*/ (private)(since C++23) | 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 . The name is for exposition only.
|
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
(C++23) |
the promise type (public member class) |
(C++23) |
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 <ranges> #include <iostream> std::generator<char> letters(char first) { for (;; co_yield first++); } int main() { for (const char ch : letters('a') | std::views::take(032)) std::cout << ch << ' '; std::cout << '\n'; }
Output:
a b c d e f g h i j k l m n o p q r s t u v w x y z
See also
(C++20) |
creates a coroutine handle that has no observable effects when resumed or destroyed (function) |