29#ifndef _GLIBCXX_GENERATOR
30#define _GLIBCXX_GENERATOR
34#pragma GCC system_header
39#define __glibcxx_want_generator
42#ifdef __cpp_lib_generator
46#include <bits/elements_of.h>
47#include <bits/uses_allocator.h>
62namespace std _GLIBCXX_VISIBILITY(default)
64_GLIBCXX_BEGIN_NAMESPACE_VERSION
81 template<
typename _Ref,
typename _Val =
void,
typename _Alloc =
void>
89 template<
typename _Ref,
typename _Val>
90 using _Reference_t = __conditional_t<is_void_v<_Val>,
94 template<
typename _Reference>
95 using _Yield_t = __conditional_t<is_reference_v<_Reference>,
100 template<
typename _Ref,
typename _Val>
101 using _Yield2_t = _Yield_t<_Reference_t<_Ref, _Val>>;
103 template<
typename>
constexpr bool __is_generator =
false;
104 template<
typename _Val,
typename _Ref,
typename _Alloc>
105 constexpr bool __is_generator<std::generator<_Val, _Ref, _Alloc>> =
true;
109 template<
typename _Yielded>
110 class _Promise_erased
112 static_assert(is_reference_v<_Yielded>);
113 using _Yielded_deref = remove_reference_t<_Yielded>;
114 using _Yielded_decvref = remove_cvref_t<_Yielded>;
115 using _ValuePtr = add_pointer_t<_Yielded>;
116 using _Coro_handle = std::coroutine_handle<_Promise_erased>;
118 template<
typename,
typename,
typename>
119 friend class std::generator;
121 template<
typename _Gen>
122 struct _Recursive_awaiter;
124 friend struct _Recursive_awaiter;
125 struct _Copy_awaiter;
126 struct _Subyield_state;
127 struct _Final_awaiter;
130 initial_suspend() const noexcept
134 yield_value(_Yielded __val)
noexcept
141 yield_value(
const _Yielded_deref& __val)
142 noexcept (is_nothrow_constructible_v<_Yielded_decvref,
143 const _Yielded_deref&>)
144 requires (is_rvalue_reference_v<_Yielded>
145 && constructible_from<_Yielded_decvref,
146 const _Yielded_deref&>)
147 {
return _Copy_awaiter(_Yielded_decvref(__val), _M_bottom_value()); }
149 template<
typename _R2,
typename _V2,
typename _A2,
typename _U2>
150 requires std::same_as<_Yield2_t<_R2, _V2>, _Yielded>
152 yield_value(ranges::elements_of<generator<_R2, _V2, _A2>&&, _U2> __r)
154 {
return _Recursive_awaiter {
std::move(__r.range) }; }
159 template<
typename _R2,
typename _V2,
typename _A2,
typename _U2>
160 requires std::same_as<_Yield2_t<_R2, _V2>, _Yielded>
162 yield_value(ranges::elements_of<generator<_R2, _V2, _A2>&, _U2> __r)
164 {
return _Recursive_awaiter {
std::move(__r.range) }; }
169 template<ranges::input_range _R,
typename _Alloc>
170 requires convertible_to<ranges::range_reference_t<_R>, _Yielded>
172 yield_value(ranges::elements_of<_R, _Alloc> __r)
174 auto __n = [] (allocator_arg_t, _Alloc,
175 ranges::iterator_t<_R> __i,
176 ranges::sentinel_t<_R> __s)
177 -> generator<_Yielded, void, _Alloc> {
178 for (; __i != __s; ++__i)
179 co_yield static_cast<_Yielded
>(*__i);
181 return yield_value(ranges::elements_of(__n(allocator_arg,
183 ranges::begin(__r.range),
184 ranges::end(__r.range))));
189 final_suspend() noexcept
193 unhandled_exception()
200 if (_M_nest._M_is_bottom())
206 void await_transform() =
delete;
207 void return_void() const noexcept {}
211 _M_bottom_value() noexcept
212 {
return _M_nest._M_bottom_value(*
this); }
216 {
return _M_nest._M_value(*
this); }
218 _Subyield_state _M_nest;
219 std::exception_ptr _M_except;
222 template<
typename _Yielded>
223 struct _Promise_erased<_Yielded>::_Subyield_state
227 _Coro_handle _M_bottom;
228 _Coro_handle _M_parent;
234 _ValuePtr _M_value =
nullptr;
243 _M_is_bottom() const noexcept
244 {
return !std::holds_alternative<_Frame>(this->_M_stack); }
249 if (
auto __f = std::get_if<_Frame>(&this->_M_stack))
250 return __f->_M_bottom.promise()._M_nest._M_top();
252 auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack);
253 __glibcxx_assert(__bf);
258 _M_push(_Coro_handle __current, _Coro_handle __subyield)
noexcept
260 __glibcxx_assert(&__current.promise()._M_nest ==
this);
261 __glibcxx_assert(this->_M_top() == __current);
263 __subyield.promise()._M_nest._M_jump_in(__current, __subyield);
266 std::coroutine_handle<>
269 if (
auto __f = std::get_if<_Frame>(&this->_M_stack))
273 auto __p = this->_M_top() = __f->_M_parent;
278 return std::noop_coroutine();
282 _M_jump_in(_Coro_handle __rest, _Coro_handle __new)
noexcept
284 __glibcxx_assert(&__new.promise()._M_nest ==
this);
285 __glibcxx_assert(this->_M_is_bottom());
290 __glibcxx_assert(!this->_M_top());
292 auto& __rn = __rest.promise()._M_nest;
293 __rn._M_top() = __new;
296 auto __bott = __rest;
297 if (
auto __f = std::get_if<_Frame>(&__rn._M_stack))
301 __bott = __f->_M_bottom;
303 this->_M_stack = _Frame {
310 _M_bottom_value(_Promise_erased& __current)
noexcept
312 __glibcxx_assert(&__current._M_nest ==
this);
313 if (
auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack))
314 return __bf->_M_value;
315 auto __f = std::get_if<_Frame>(&this->_M_stack);
316 __glibcxx_assert(__f);
317 auto& __p = __f->_M_bottom.promise();
318 return __p._M_nest._M_value(__p);
322 _M_value(_Promise_erased& __current)
noexcept
324 __glibcxx_assert(&__current._M_nest ==
this);
325 auto __bf = std::get_if<_Bottom_frame>(&this->_M_stack);
326 __glibcxx_assert(__bf);
327 return __bf->_M_value;
331 template<
typename _Yielded>
332 struct _Promise_erased<_Yielded>::_Final_awaiter
334 bool await_ready() noexcept
337 template<
typename _Promise>
338 auto await_suspend(std::coroutine_handle<_Promise> __c)
noexcept
340#ifdef __glibcxx_is_pointer_interconvertible
342 _Promise_erased, _Promise>);
345 auto& __n = __c.promise()._M_nest;
349 void await_resume() noexcept {}
352 template<
typename _Yielded>
353 struct _Promise_erased<_Yielded>::_Copy_awaiter
355 _Yielded_decvref _M_value;
356 _ValuePtr& _M_bottom_value;
358 constexpr bool await_ready() noexcept
361 template<
typename _Promise>
362 void await_suspend(std::coroutine_handle<_Promise>)
noexcept
364#ifdef __glibcxx_is_pointer_interconvertible
366 _Promise_erased, _Promise>);
372 await_resume() const noexcept
376 template<
typename _Yielded>
377 template<
typename _Gen>
378 struct _Promise_erased<_Yielded>::_Recursive_awaiter
381 static_assert(__is_generator<_Gen>);
382 static_assert(std::same_as<typename _Gen::yielded, _Yielded>);
384 _Recursive_awaiter(_Gen __gen) noexcept
386 { this->_M_gen._M_mark_as_started(); }
389 await_ready() const noexcept
393 template<
typename _Promise>
394 std::coroutine_handle<>
395 await_suspend(std::coroutine_handle<_Promise> __p)
noexcept
397#ifdef __glibcxx_is_pointer_interconvertible
399 _Promise_erased, _Promise>);
402 auto __c = _Coro_handle::from_address(__p.address());
403 auto __t = _Coro_handle::from_address(this->_M_gen._M_coro.address());
404 __p.promise()._M_nest._M_push(__c, __t);
410 if (
auto __e = _M_gen._M_coro.promise()._M_except)
417 alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__)
418 char _M_data[__STDCPP_DEFAULT_NEW_ALIGNMENT__];
421 _M_cnt(std::size_t __sz)
noexcept
423 auto __blksz =
sizeof(_Alloc_block);
424 return (__sz + __blksz - 1) / __blksz;
428 template<
typename _All>
429 concept _Stateless_alloc
430 = default_initializable<_All>
431 && allocator_traits<_All>::is_always_equal::value;
433 template<
typename _Allocator>
436 using _Rebound = __alloc_rebind<_Allocator, _Alloc_block>;
437 using _Rebound_ATr = allocator_traits<_Rebound>;
438 static_assert(is_pointer_v<typename _Rebound_ATr::pointer>,
439 "Must use allocators for true pointers with generators");
442 _M_alloc_address(std::uintptr_t __fn, std::uintptr_t __fsz)
noexcept
444 auto __an = __fn + __fsz;
445 auto __ba =
alignof(_Rebound);
446 return reinterpret_cast<_Rebound*
>(((__an + __ba - 1) / __ba) * __ba);
450 _M_alloc_size(std::size_t __csz)
noexcept
452 auto __ba =
alignof(_Rebound);
457 return __csz + __ba +
sizeof(_Rebound);
461 _M_allocate(_Rebound __b, std::size_t __csz)
463 if constexpr (_Stateless_alloc<_Rebound>)
465 return __b.allocate(_Alloc_block::_M_cnt(__csz));
468 auto __nsz = _Alloc_block::_M_cnt(_M_alloc_size(__csz));
469 auto __f = __b.allocate(__nsz);
470 auto __fn =
reinterpret_cast<std::uintptr_t
>(__f);
471 auto __an = _M_alloc_address(__fn, __csz);
479 operator new(std::size_t __sz)
480 requires default_initializable<_Rebound>
481 {
return _M_allocate({}, __sz); }
486 template<
typename _Alloc,
typename... _Args>
488 operator new(std::size_t __sz,
489 allocator_arg_t,
const _Alloc& __a,
492 static_assert(convertible_to<const _Alloc&, _Allocator>,
493 "the allocator argument to the coroutine must be "
494 "convertible to the generator's allocator type");
495 return _M_allocate(_Rebound(_Allocator(__a)), __sz);
498 template<
typename _This,
typename _Alloc,
typename... _Args>
500 operator new(std::size_t __sz,
502 allocator_arg_t,
const _Alloc& __a,
505 static_assert(convertible_to<const _Alloc&, _Allocator>,
506 "the allocator argument to the coroutine must be "
507 "convertible to the generator's allocator type");
508 return _M_allocate(_Rebound(_Allocator(__a)), __sz);
512 operator delete(
void* __ptr, std::size_t __csz)
noexcept
514 if constexpr (_Stateless_alloc<_Rebound>)
517 return __b.deallocate(
reinterpret_cast<_Alloc_block*
>(__ptr),
518 _Alloc_block::_M_cnt(__csz));
522 auto __nsz = _Alloc_block::_M_cnt(_M_alloc_size(__csz));
523 auto __fn =
reinterpret_cast<std::uintptr_t
>(__ptr);
524 auto __an = _M_alloc_address(__fn, __csz);
527 __b.deallocate(
reinterpret_cast<_Alloc_block*
>(__ptr), __nsz);
533 class _Promise_alloc<void>
535 using _Dealloc_fn = void (*)(
void*, std::size_t);
538 _M_dealloc_address(std::uintptr_t __fn, std::uintptr_t __fsz)
noexcept
540 auto __an = __fn + __fsz;
541 auto __ba =
alignof(_Dealloc_fn);
542 auto __aligned = ((__an + __ba - 1) / __ba) * __ba;
543 return reinterpret_cast<_Dealloc_fn*
>(__aligned);
546 template<
typename _Rebound>
548 _M_alloc_address(std::uintptr_t __fn, std::uintptr_t __fsz)
noexcept
549 requires (!_Stateless_alloc<_Rebound>)
551 auto __ba =
alignof(_Rebound);
552 auto __da = _M_dealloc_address(__fn, __fsz);
553 auto __aan =
reinterpret_cast<std::uintptr_t
>(__da);
554 __aan +=
sizeof(_Dealloc_fn);
555 auto __aligned = ((__aan + __ba - 1) / __ba) * __ba;
556 return reinterpret_cast<_Rebound*
>(__aligned);
559 template<
typename _Rebound>
561 _M_alloc_size(std::size_t __csz)
noexcept
565 std::size_t __aa = 0;
566 std::size_t __as = 0;
567 if constexpr (!std::same_as<_Rebound, void>)
569 __aa =
alignof(_Rebound);
570 __as =
sizeof(_Rebound);
572 auto __ba = __aa +
alignof(_Dealloc_fn);
573 return __csz + __ba + __as +
sizeof(_Dealloc_fn);
576 template<
typename _Rebound>
578 _M_deallocator(
void* __ptr, std::size_t __csz)
noexcept
580 auto __asz = _M_alloc_size<_Rebound>(__csz);
581 auto __nblk = _Alloc_block::_M_cnt(__asz);
583 if constexpr (_Stateless_alloc<_Rebound>)
586 __b.deallocate(
reinterpret_cast<_Alloc_block*
>(__ptr), __nblk);
590 auto __fn =
reinterpret_cast<std::uintptr_t
>(__ptr);
591 auto __an = _M_alloc_address<_Rebound>(__fn, __csz);
594 __b.deallocate(
reinterpret_cast<_Alloc_block*
>(__ptr), __nblk);
598 template<
typename _Alloc>
600 _M_allocate(
const _Alloc& __a, std::size_t __csz)
602 using _Rebound = __alloc_rebind<_Alloc, _Alloc_block>;
603 using _Rebound_ATr = allocator_traits<_Rebound>;
605 static_assert(is_pointer_v<typename _Rebound_ATr::pointer>,
606 "Must use allocators for true pointers with generators");
608 _Dealloc_fn __d = &_M_deallocator<_Rebound>;
609 auto __b =
static_cast<_Rebound
>(__a);
610 auto __asz = _M_alloc_size<_Rebound>(__csz);
611 auto __nblk = _Alloc_block::_M_cnt(__asz);
612 void* __p = __b.allocate(__nblk);
613 auto __pn =
reinterpret_cast<std::uintptr_t
>(__p);
614 *_M_dealloc_address(__pn, __csz) = __d;
615 if constexpr (!_Stateless_alloc<_Rebound>)
617 auto __an = _M_alloc_address<_Rebound>(__pn, __csz);
624 operator new(std::size_t __sz)
626 auto __nsz = _M_alloc_size<void>(__sz);
627 _Dealloc_fn __d = [] (
void* __ptr, std::size_t __sz)
629 ::operator
delete(__ptr, _M_alloc_size<void>(__sz));
631 auto __p = ::operator
new(__nsz);
632 auto __pn =
reinterpret_cast<uintptr_t
>(__p);
633 *_M_dealloc_address(__pn, __sz) = __d;
637 template<
typename _Alloc,
typename... _Args>
639 operator new(std::size_t __sz,
640 allocator_arg_t,
const _Alloc& __a,
642 {
return _M_allocate(__a, __sz); }
644 template<
typename _This,
typename _Alloc,
typename... _Args>
646 operator new(std::size_t __sz,
648 allocator_arg_t,
const _Alloc& __a,
650 {
return _M_allocate(__a, __sz); }
653 operator delete(
void* __ptr, std::size_t __sz)
noexcept
656 auto __pn =
reinterpret_cast<uintptr_t
>(__ptr);
657 __d = *_M_dealloc_address(__pn, __sz);
662 template<
typename _Tp>
663 concept _Cv_unqualified_object = is_object_v<_Tp>
664 && same_as<_Tp, remove_cv_t<_Tp>>;
668 template<
typename _Ref,
typename _Val,
typename _Alloc>
672 using _Value = __conditional_t<is_void_v<_Val>,
673 remove_cvref_t<_Ref>,
675 static_assert(__gen::_Cv_unqualified_object<_Value>,
676 "Generator value must be a cv-unqualified object type");
677 using _Reference = __gen::_Reference_t<_Ref, _Val>;
678 static_assert(is_reference_v<_Reference>
679 || (__gen::_Cv_unqualified_object<_Reference>
680 && copy_constructible<_Reference>),
681 "Generator reference type must be either a cv-unqualified "
682 "object type that is trivially constructible or a "
685 using _RRef = __conditional_t<
686 is_reference_v<_Reference>,
687 remove_reference_t<_Reference>&&,
691 static_assert(common_reference_with<_Reference&&, _Value&&>);
692 static_assert(common_reference_with<_Reference&&, _RRef&&>);
693 static_assert(common_reference_with<_RRef&&, const _Value&>);
695 using _Yielded = __gen::_Yield_t<_Reference>;
696 using _Erased_promise = __gen::_Promise_erased<_Yielded>;
700 friend _Erased_promise;
701 friend struct _Erased_promise::_Subyield_state;
703 using yielded = _Yielded;
705 struct promise_type : _Erased_promise, __gen::_Promise_alloc<_Alloc>
707 generator get_return_object() noexcept
708 {
return { coroutine_handle<promise_type>::from_promise(*
this) }; }
711#ifdef __glibcxx_is_pointer_interconvertible
716 generator(
const generator&) =
delete;
718 generator(generator&& __other) noexcept
719 : _M_coro(std::__exchange(__other._M_coro,
nullptr)),
720 _M_began(std::__exchange(__other._M_began,
false))
725 if (
auto& __c = this->_M_coro)
730 operator=(generator __other)
noexcept
732 swap(__other._M_coro, this->_M_coro);
733 swap(__other._M_began, this->_M_began);
740 this->_M_mark_as_started();
741 auto __h = _Coro_handle::from_promise(_M_coro.promise());
742 __h.promise()._M_nest._M_top() = __h;
751 using _Coro_handle = std::coroutine_handle<_Erased_promise>;
753 generator(coroutine_handle<promise_type> __coro) noexcept
754 : _M_coro { move(__coro) }
758 _M_mark_as_started() noexcept
760 __glibcxx_assert(!this->_M_began);
761 this->_M_began =
true;
764 coroutine_handle<promise_type> _M_coro;
765 bool _M_began =
false;
768 template<
class _Ref,
class _Val,
class _Alloc>
769 struct generator<_Ref, _Val, _Alloc>::_Iterator
771 using value_type = _Value;
772 using difference_type = ptrdiff_t;
775 operator==(
const _Iterator& __i, default_sentinel_t)
noexcept
776 {
return __i._M_coro.done(); }
778 friend class generator;
780 _Iterator(_Iterator&& __o) noexcept
781 : _M_coro(std::__exchange(__o._M_coro, {}))
785 operator=(_Iterator&& __o)
noexcept
787 this->_M_coro = std::__exchange(__o._M_coro, {});
800 { this->operator++(); }
804 const noexcept(is_nothrow_move_constructible_v<_Reference>)
806 auto& __p = this->_M_coro.promise();
807 return static_cast<_Reference
>(*__p._M_value());
811 friend class generator;
813 _Iterator(_Coro_handle __g)
819 auto& __t = this->_M_coro.promise()._M_nest._M_top();
823 _Coro_handle _M_coro;
830 template<
typename _Ref,
typename _Val =
void>
831 using generator = std::generator<_Ref, _Val, polymorphic_allocator<std::byte>>;
835_GLIBCXX_END_NAMESPACE_VERSION
constexpr complex< _Tp > operator*(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x times y.
constexpr bool is_pointer_interconvertible_base_of_v
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
exception_ptr current_exception() noexcept
void rethrow_exception(exception_ptr)
Throw the object pointed to by the exception_ptr.
ISO C++ entities toplevel namespace is std.
constexpr default_sentinel_t default_sentinel
A default sentinel value.
The ranges::view_interface class template.