From 10104b8ac175e292e88e50298e01e5d16979ea6d Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 19 Jan 2025 16:40:26 +0100 Subject: [PATCH] libtuil: allow non-default-constructible types in generators references remain forbidden because std::optional does not want to contain them, and specializing generators to use pointers where we can't use optionals is simply too much work for a feature we don't even need. reference wrappers and bindings still work well enough. Change-Id: I2e6ca74719584ce16e2357c452fdd5c5a9e23d5a --- lix/libutil/generator.hh | 8 ++++---- tests/unit/libutil/generator.cc | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/lix/libutil/generator.hh b/lix/libutil/generator.hh index e81a7f7c8..e5d2e6024 100644 --- a/lix/libutil/generator.hh +++ b/lix/libutil/generator.hh @@ -39,9 +39,9 @@ struct failure template struct promise_state { - // result of the most recent coroutine resumption: a value, - // a nested coroutine to drain, an error, or our completion - std::variant, failure, finished> value{}; + // result of the most recent coroutine resumption: a nested + // coroutine to drain, a value, an error, or our completion + std::variant, T, failure, finished> value{}; // coroutine to resume when this one has finished. set when // one generator yields another, such that the entire chain // of parents always linearly points to the root generator. @@ -86,7 +86,7 @@ struct promise : promise_state } std::suspend_always yield_value(From && from) { - this->value.template emplace<0>(convert(std::forward(from))); + this->value.template emplace<1>(convert(std::forward(from))); return {}; } diff --git a/tests/unit/libutil/generator.cc b/tests/unit/libutil/generator.cc index b08cb29bb..5b5622a70 100644 --- a/tests/unit/libutil/generator.cc +++ b/tests/unit/libutil/generator.cc @@ -260,4 +260,20 @@ TEST(Generator, iterators) } } +TEST(Generator, nonDefaultCtor) +{ + auto g = []() -> Generator> { + int i = 0; + co_yield i; + i += 1; + co_yield i; + }(); + + auto i = g.next(); + ASSERT_EQ(*i, 0); + i->get() = 10; + i = g.next(); + ASSERT_EQ(*i, 11); +} + }