#include #include #include #include template struct Generator { struct promise_type; using handle_type = std::coroutine_handle; struct promise_type { T value_; std::exception_ptr exception_; Generator get_return_object() { return Generator(handle_type::from_promise(*this)); } std::suspend_always initial_suspend() { return {}; } std::suspend_always final_suspend() noexcept { return {}; } void unhandled_exception() { exception_ = std::current_exception(); } template From> std::suspend_always yield_value(From&& from) { value_ = std::forward(from); return {}; } void return_void() {} }; handle_type h_; Generator(handle_type h) : h_(h) {} ~Generator() { h_.destroy(); } explicit operator bool() { fill(); return !h_.done(); } T operator()() { fill(); full_ = false; return std::move(h_.promise().value_); } private: bool full_ = false; void fill() { if(!full_) { h_(); if(h_.promise().exception_) { std::rethrow_exception(h_.promise().exception_); } full_ = true; } } }; Generator fib(unsigned n) { if(n == 0) co_return; if(n > 94) { throw std::runtime_error("Too big"); } if(n == 1) co_return; co_yield 1; if(n == 2) co_return; std::uint64_t a = 0; std::uint64_t b = 1; for(unsigned i = 2; i < n; ++i) { std::uint64_t s = a + b; co_yield s; a = b; b = s; } } int main() { try { auto gen = fib(50); for(int j = 0; gen; ++j) { fmt::println("fib({})={}", j, gen()); } } catch(const std::exception& ex) { fmt::println("Exception: {}", ex.what()); } catch(...) { fmt::println("Unknown exception"); } return 0; }