generator::promise_type::yield_value(ranges::elements_of<Rng, Alloc>)
should not be noexcept
Section: 25.8.5 [coro.generator.promise] Status: WP Submitter: Tim Song Opened: 2023-02-25 Last modified: 2023-11-22
Priority: Not Prioritized
View other active issues in [coro.generator.promise].
View all other issues in [coro.generator.promise].
View all issues with WP status.
Discussion:
The overload of yield_value
for yielding elements of arbitrary ranges does so by creating a nested generator,
but to do so it needs to:
call ranges::begin
/ranges::end
on the range
allocate a new coroutine frame (unless the allocation is elided by the compiler, which isn't guaranteed)
copy/move the iterator and sentinel into the coroutine frame
All of these are allowed to throw, so this overload should not be noexcept
.
[2023-03-22; Reflector poll]
Set status to Tentatively Ready after six votes in favour during reflector poll.
[2023-06-17 Approved at June 2023 meeting in Varna. Status changed: Voting → WP.]
Proposed resolution:
This wording is relative to N4928.
Modify 25.8.5 [coro.generator.promise] as indicated:
[…]namespace std { template<class Ref, class V, class Allocator> class generator<Ref, V, Allocator>::promise_type { public: […] auto yield_value(const remove_reference_t<yielded>& lval) requires is_rvalue_reference_v<yielded> && constructible_from<remove_cvref_t<yielded>, const remove_reference_t<yielded>&>; template<class R2, class V2, class Alloc2, class Unused> requires same_as<typename generator<R2, V2, Alloc2>::yielded, yielded> auto yield_value(ranges::elements_of<generator<R2, V2, Alloc2>&&, Unused> g) noexcept; template<ranges::input_range R, class Alloc> requires convertible_to<ranges::range_reference_t<R>, yielded> auto yield_value(ranges::elements_of<R, Alloc> r)noexcept; […] }; }template<ranges::input_range R, class Alloc> requires convertible_to<ranges::range_reference_t<R>, yielded> auto yield_value(ranges::elements_of<R, Alloc> r)noexcept;-13- Effects: Equivalent to:
[…]auto nested = [](allocator_arg_t, Alloc, ranges::iterator_t<R> i, ranges::sentinel_t<R> s) -> generator<yielded, ranges::range_value_t<R>, Alloc> { for (; i != s; ++i) { co_yield static_cast<yielded>(*i); } }; return yield_value(ranges::elements_of(nested( allocator_arg, r.allocator, ranges::begin(r.range), ranges::end(r.range))));