CppCoroutines (C++20)

Coroutines (C++20)

A coroutine is a function that can suspend its execution partway through, return control to its caller, and later be resumed from exactly where it left off — with all of its local state intact. This is a different execution model from a normal function, which always runs to completion once called. Coroutines are especially well suited to problems that are naturally about producing a sequence of values or waiting on something over time: generators that yield one value at a time, asynchronous I/O that suspends while waiting on a network response, and lazy sequences that only compute the next value when it's actually requested.
The new keywords

Keyword

Meaning

co_await

Suspend execution until the awaited operation completes

co_yield

Suspend execution and produce a value back to the caller (used for generators)

co_return

Finish the coroutine, optionally producing a final result

Using any of these three keywords anywhere in a function's body automatically makes that function a coroutine — the compiler transforms it behind the scenes into a state machine capable of suspending and resuming.

A conceptual generator example
The example below sketches what a simple generator coroutine looks like conceptually, producing successive integers with co_yield. Note that Generator<T> here is not a standard library type — C++20 provides only the low-level co_yield/co_await/co_return keywords and a set of compiler hooks; the Generator return type itself has to be implemented (its promise_type, iterator, etc.) either by hand or via a coroutine support library.

Conceptual sketch of a generator coroutine

CPP
// Conceptual only -- Generator<T> is a user- or library-defined type,
// not something the standard library hands you out of the box.
Generator<int> countUpTo(int limit) {
    for (int i = 1; i <= limit; ++i) {
        co_yield i; // suspend here, hand 'i' back to the caller
    }
    co_return; // coroutine finished
}

void useGenerator() {
    for (int value : countUpTo(5)) {
        // Each iteration resumes the coroutine from where it
        // last suspended, producing 1, 2, 3, 4, 5 one at a time.
        std::cout << value << " ";
    }
}
C++20 coroutines are a low-level building block, not a ready-made feature
Unlike languages with built-in generator or async/await sugar backed by a runtime, C++20 shipped only the co_await/co_yield/co_return keywords and a customization-point protocol (promise types, awaiters, coroutine handles) that a library author uses to build an actual usable type like the Generator<T> above. Implementing that machinery from scratch is verbose and easy to get subtly wrong. In practice, most C++ developers consume coroutines through a library that has already done this work — such as cppcoro, or coroutine support added by frameworks and newer standard library proposals — rather than writing the promise-type boilerplate themselves.
  • A coroutine is a function that can suspend and resume, preserving its local state between suspensions.

  • co_await suspends on an operation, co_yield suspends while producing a value, co_return ends the coroutine.

  • Coroutines suit generators, lazy sequences, and asynchronous I/O particularly well.

  • Raw C++20 coroutines are a low-level toolkit; most developers use them via a library rather than writing the supporting machinery themselves.