Skip to content

Coroutines (C++20) ​

In a Nutshell ​

A language mechanism that lets a function suspend mid-execution and resume later—the infrastructure for implementing patterns such as lazy generators, asynchronous I/O, and state machines.

#include <coroutine> (coroutine support library)

Core API Cheat Sheet ​

OperationSignatureDescription
Coroutine handlecoroutine_handle<promise_type>Type-erased coroutine handle, used to resume/destroy
Suspendco_await expr;Suspends the current coroutine, waiting for expr to complete
Yield a valueco_yield expr;Suspends and returns a value to the caller
Returnco_return expr;Final return of the coroutine
Promise typestruct promise_typeThe type that customizes coroutine behavior (must be defined inside the return type)
Initial suspend pointsuspend_always initial_suspend()Whether the coroutine suspends immediately upon start
Final suspend pointsuspend_always final_suspend() noexceptWhether the coroutine suspends upon completion (noexcept is mandatory)
Return objectget_return_object()Creates the object returned to the caller

Minimal Example ​

Expand codeCollapse31 lines
C++
// Standard: C++20
#include <coroutine>
#include <iostream>

struct Generator {
    struct promise_type {
        int current_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{}; }
        auto yield_value(int v) { current_value = v; return std::suspend_always{}; }
        void return_void() {}
        void unhandled_exception() {}
    };
    using handle = std::coroutine_handle<promise_type>;
    handle coro;
    ~Generator() { if (coro) coro.destroy(); }
    bool next() { coro.resume(); return !coro.done(); }
    int value() { return coro.promise().current_value; }
};

Generator counter() {
    for (int i = 0; i < 3; ++i)
        co_yield i;
}

int main() {
    auto gen = counter();
    while (gen.next())
        std::cout << gen.value() << " "; // 0 1 2
}

Embedded Applicability: Medium ​

  • Stackless coroutines: when suspended, the state lives in a heap-allocated coroutine frame, so memory overhead is controllable
  • A good fit for embedded asynchronous I/O, event loops, state machines, and similar patterns, replacing callback hell
  • Coroutine frames are heap-allocated by default; a custom operator new can redirect them to a static memory pool
  • C++20 provides only the language mechanism and minimal library support; practical high-level abstractions (such as std::generator) require C++23
  • Compiler support still has known ICEs (internal compiler errors); test thoroughly before production use

Compiler Support ​

GCCClangMSVC
121419.28

See Also ​


Part of the content referenced from cppreference.com, licensed under CC-BY-SA 4.0

pdf-latest-4-g85128cc · 85128cc · 2026-10-05