cplusplus / nbballot

Handling of NB comments in response to ballots
14 stars 4 forks source link

US 55-117 26.8.5p10 [coro.generator.promise] Yielding from a partially-executed generator #530

Closed wg21bot closed 1 year ago

wg21bot commented 1 year ago

There doesn't seem to be a reason to forbid yielding from a partially executed generator.

Proposed change:

Require merely that g.range.coroutine_ be suspended and not at its final suspend point.

CaseyCarter commented 1 year ago

generator::begin has a precondition that the generator's coroutine handle refers to a coroutine suspended at its initial suspend point. This is necessary since begin resumes the coroutine so it can yield the first element of the generated range so it is ready to be retrieved from the returned iterator's operator*. We don't call begin on recursive generators, but we must similarly resume a recursively yielded coroutine to allow it to generate an element before the iterator observes that element. A partially executed coroutine will already have a "current" element that would be effectively skipped by the iteration if we permitted it to be yielded recursively, disappearing into the ether.

This precondition also prevents a generator recursively yielding itself. For example:

std::generator<int> x;

std::generator<int> foo() {
  co_yield std::ranges::elements_of(std::move(x));
}

int main() {
  x = foo();
  for (auto&& meow : x) {
    // ...
  }
}

we suspect that the other requirements on generator are unimplementable, or at the very least not efficiently implementable, for self-recursive generators - we'd need another way to forbid this.

All of which is to say that the preconditions are subtle, and that the requested relaxation needs some investigation (i.e., a paper) to ensure there's no ancillary damage. There seems to be no impediment to making such a change after shipping C++23 with such a paper in hand.

jensmaurer commented 1 year ago

Rejected. There is no consensus for a change.