...

/

An Introduction to C++ Coroutines

An Introduction to C++ Coroutines

Learn about C++ coroutines, including coroutine abstraction, and learn to differentiate them from subroutines through examples.

A few motivating examples

Coroutines are one of those features, similar to lambda expressions, that offer a way to completely change the way we write and think about C++ code. The concept is very general and can be applied in many different ways. To give you a taste of how C++ can look when using coroutines, we will here look briefly at two examples.

Yield-expressions can be used for implementing generators—objects that produce sequences of values lazily. In this example, we will use the keywords co_yield and co_return to control the flow:

Press + to interact
main.cpp
generator.h
chapter_12.h
auto iota(int start) -> Generator<int> {
for (int i = start; i < std::numeric_limits<int>::max(); ++i) {
co_yield i;
}
}
auto take_until(Generator<int>& gen, int value) -> Generator<int> {
for (auto v : gen) {
if (v == value) {
co_return;
}
co_yield v;
}
}
int main() {
auto i = iota(2);
auto t = take_until(i, 5);
for (auto v : t) {
std::cout << v << ", ";
}
return 0;
}

In the preceding example, iota() and take_until() are coroutines. iota() generates a sequence of integers and take_until() yields values until it finds the specified value. The Generator template is a custom type that we will show you how to design and implement later on in this chapter.

Building generators is one common use case for coroutines; another one is implementing asynchronous tasks. The next example will demonstrate how we can use the operator co_await to ...