Below is the code:
// Example program
#include <iostream>
#include <string>
#include <memory>
#include <vector>
#include <coroutine>
template <typename T>
class Generator {
public:
struct promise_type {
T value;
std::suspend_always yield_value(T v) { value = v; return {}; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() { std::terminate(); }
Generator get_return_object() { return Generator{ Handle::from_promise(*this) }; }
};
struct Handle : std::coroutine_handle<promise_type> {
Handle(std::coroutine_handle<promise_type> h) : std::coroutine_handle<promise_type>(h) {}
T& operator()() { return this->promise().value; }
void operator++() { this->resume(); }
};
Generator(Handle h) : handle(h) {}
~Generator() { if (handle) handle.destroy(); }
T& operator()() { return handle(); }
void operator++() { ++handle; }
explicit operator bool() { return !handle.done(); }
//private:
Handle handle{};
};
Generator<int> generateNumbers(int start, int end) {
for (int i = start; i <= end; ++i) {
co_yield i;
}
}
int main()
{
auto gen = generateNumbers(1, 10); // Adjust the range as needed
while (gen) {
if(gen.handle.done()) // I also tried directly accessing the handle, but this did also not work.
break;
std::cout << gen() << std::endl;
++gen;
}
}
In this code I am creating a generator as a coroutine Generator class. Now I want to use this generator to generate some numbers in the generateNumbers function. I call this from main and try to iterate over the numbers. The problem is when I want to check if the iteration is over. I try checking the generator as a bool in the while. The overwritten bool operator calls the handle.done(), I checked in the debugger and it does so. The problem is that the handle.done() always returns false, even when the loop is indeed over. I tried calling handle.done() directly from within the loop, this also did not work.
I am using a compiler supporting the C++20 standard.
Can you help me understand my mistake? Thank you very much.
done()
returns true
if the coroutine is suspended at its final suspend point.
Your final_suspend()
returns std::suspend_never
, so the coroutine will not be suspended at its final suspend point. You need to change it to return std::suspend_always
.