There are two use-cases where I regularly use
coroutines:
Writing
generators to "lazily" create a sequence of elements, i.e. only generate each element of the sequence when it's actually needed. And, most important,
GUI programming. Actually, I'm using
async
functions in C# (which essentially are coroutines) a whole lot! This way you can write "non-blocking" functions, i.e. functions that run directly in the GUI thread but that still won't "freeze" your GUI while waiting for I/O operations (or the like) to complete. That is
so much more elegant and less error-prone than having to kick off a separate thread for each "long-running", e.g. I/O, operation – and then having to explicitly synchronize with the GUI thread in order to "show" the result 🙄
As far as C++ is concerned, I think the coroutines support added in C++20 is more a "low level" feature, which is mostly intended for library developers. Even if you look at "minimal" C++ coroutine examples, they require an amazing amount of boilerplate code, because of all the return types and promise types that need to be defined! That's probably the reason why C++ coroutines are
not used so much yet...
std::generator
from C++23 seems like a big step forward:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
#include <generator>
#include <ranges>
#include <iostream>
std::generator<char> letters(char first)
{
for (;; co_yield first++);
}
int main()
{
for (const char ch : letters('a') | std::views::take(26))
std::cout << ch << ' ';
std::cout << '\n';
}
|