78 std::exception_ptr exception;
79 std::coroutine_handle<promise_type> parent;
80 std::coroutine_handle<promise_type> root;
87 explicit YieldNested(Generator&& nested_) noexcept : nested(std::move(nested_)) {}
89 [[nodiscard]]
bool await_ready()
const noexcept {
return !nested.handle; }
91 std::coroutine_handle<promise_type> await_suspend(std::coroutine_handle<promise_type> h)
noexcept {
92 auto nestedHandle = nested.handle;
93 nestedInfo.parent = h;
94 if (
auto* info = h.promise().tryGetNestInfo()) {
95 nestedInfo.root = info->root;
100 nestedInfo.root.promise().setTop(nestedHandle);
101 nestedHandle.promise().setNestInfo(std::addressof(nestedInfo));
105 void await_resume() {
106 if (nestedInfo.exception) {
107 std::rethrow_exception(nestedInfo.exception);
112 std::add_pointer_t<yielded> ptr =
nullptr;
114 reinterpret_cast<uintptr_t
>(std::coroutine_handle<promise_type>::from_promise(*this).address());
117 constexpr bool await_ready()
const noexcept {
return false; }
119 constexpr std::coroutine_handle<> await_suspend(std::coroutine_handle<promise_type> h)
noexcept {
120 if (
auto* info = h.promise().tryGetNestInfo()) {
121 info->root.promise().setTop(info->parent);
125 return std::noop_coroutine();
128 constexpr void await_resume()
const noexcept {}
131 Generator get_return_object() noexcept {
return Generator{*
this}; }
133 std::suspend_always initial_suspend() noexcept {
return {}; }
135 FinalAwaiter final_suspend() noexcept {
return {}; }
137 void unhandled_exception() {
138 if (
auto* info = tryGetNestInfo()) {
139 info->exception = std::current_exception();
145 std::suspend_always yield_value(yielded val)
noexcept {
146 ptr = std::addressof(val);
149 auto yield_value(std::remove_reference_t<yielded>
const& lval)
150 requires std::is_rvalue_reference_v<yielded>
151 && std::constructible_from<std::remove_cvref_t<yielded>, std::remove_reference_t<yielded>
const&>
154 std::remove_cvref_t<yielded> storage;
155 constexpr YieldCopied(std::remove_reference_t<yielded>
const& v) : storage(v) {}
156 constexpr bool await_ready() const noexcept {
return false; }
157 constexpr void await_suspend(std::coroutine_handle<promise_type> h)
noexcept {
158 h.promise().ptr = std::addressof(storage);
160 constexpr void await_resume() const noexcept {}
162 return YieldCopied{lval};
166 auto yield_value(ElementsOf<Generator<U>&&> elements)
167 requires std::same_as<typename Generator<U>::yielded, yielded>
173 auto yield_value(ElementsOf<Generator<U>&> elements)
174 requires std::same_as<typename Generator<U>::yielded, yielded>
179 template <
class Range>
180 auto yield_value(ElementsOf<Range>&& elements) {
181 return YieldNested{Generator::makeElementGenerator(std::move(elements))};
183 void return_void() noexcept {}
186 U&& await_transform(U&&) =
delete;
189 [[nodiscard]]
NestInfo* tryGetNestInfo() const noexcept {
190 if ((data & 1U) != 0) {
191 return reinterpret_cast<NestInfo*
>(data ^ 1U);
197 [[nodiscard]] std::coroutine_handle<promise_type> getTop() const noexcept {
198 return std::coroutine_handle<promise_type>::from_address(
reinterpret_cast<void*
>(data));
201 void setNestInfo(
NestInfo* info)
noexcept { data =
reinterpret_cast<uintptr_t
>(info) | 1U; }
203 void setTop(std::coroutine_handle<promise_type> top)
noexcept {
204 data =
reinterpret_cast<uintptr_t
>(top.address());
207 friend struct iterator;
212 using iterator_category = std::input_iterator_tag;
213 using difference_type = ptrdiff_t;
214 using value_type = Generator::value;
215 using reference = Generator::reference;
216 using pointer = std::add_pointer_t<yielded>;
218 std::coroutine_handle<promise_type> handle =
nullptr;
220 iterator() =
default;
221 explicit iterator(std::coroutine_handle<promise_type> handle) noexcept : handle(handle) {}
223 iterator& operator++() {
224 handle.promise().getTop().resume();
232 void operator++(
int) { ++*
this; }
234 [[nodiscard]]
bool operator==(iterator
const& other)
const noexcept {
return handle == other.handle; }
236 [[nodiscard]] reference operator*()
const noexcept {
237 return static_cast<reference
>(*handle.promise().getTop().promise().ptr);
240 [[nodiscard]] pointer operator->()
const noexcept {
return handle.promise().getTop().promise().ptr; }