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;
}
How do I avoid rehashing overhead with std::set in multithreaded code?
How do I find elements with custom comparators with std::set for embedded targets?
How do I erase elements while iterating with std::set for embedded targets?
How do I provide stable iteration order with std::unordered_map for large datasets?
How do I reserve capacity ahead of time with std::unordered_map for large datasets?
How do I erase elements while iterating with std::unordered_map in multithreaded code?
How do I provide stable iteration order with std::map for embedded targets?
How do I provide stable iteration order with std::map in multithreaded code?
How do I avoid rehashing overhead with std::map in performance-sensitive code?
How do I merge two containers efficiently with std::map for embedded targets?