How do I compose coroutines with generators and tasks?

Explore how to compose coroutines using generators and tasks in C++. This guide provides an insightful example to help you understand coroutine composition efficiently.

c++, coroutines, generators, tasks, composition, asynchronous programming, C++20, concurrency

#include <iostream> #include <coroutine> #include <optional> struct Generator { struct promise_type { std::optional value; auto get_return_object() { return Generator{Handle::from_promise(*this)}; } auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() noexcept { return std::suspend_always{}; } void unhandled_exception() { std::terminate(); } auto yield_value(int v) { value = v; return std::suspend_always{}; } void return_void() {} }; using Handle = std::coroutine_handle; Handle handle; Generator(Handle h) : handle(h) {} ~Generator() { handle.destroy(); } bool next() { if (handle) { handle.resume(); return handle.done(); } return true; } int current_value() const { return *handle.promise().value; } }; Generator numbers() { for (int i = 0; i < 5; ++i) { co_yield i; // Yield values from 0 to 4 } } int main() { auto gen = numbers(); while (!gen.next()) { std::cout << gen.current_value() << "\n"; // Print current value } return 0; }

c++ coroutines generators tasks composition asynchronous programming C++20 concurrency