Skip to content

Coroutines Basics (C++20)

One-Liner

A language mechanism that allows a function to suspend (suspend) at an intermediate point and later resume (resume)—the infrastructure for implementing lazy generators, asynchronous I/O, state machines, and other patterns.

<coroutine> (Coroutine support library)

Core API Cheat Sheet

OperationSignatureDescription
Coroutine Handlestd::coroutine_handle<>Type-erased coroutine handle, used to resume/destroy
Suspendco_awaitSuspends the current coroutine, waiting for the awaiter to complete
Yield Valueco_yieldSuspends and returns a value to the caller
Returnco_returnFinal return of the coroutine
Promise Typepromise_typeType that customizes coroutine behavior (must be defined in the return type)
Initial Suspend Pointinitial_suspendWhether the coroutine suspends immediately upon startup
Final Suspend Pointfinal_suspendWhether the coroutine suspends upon exit (required for coroutine_handle to remain valid)
Return Objectget_return_objectCreates the object returned to the caller

Minimal Example

Expand (43 lines)Collapse
cpp
#include <coroutine>
#include <iostream>

struct Generator {
    struct Promise {
        int value_;
        Generator get_return_object() { return Generator{std::coroutine_handle<Promise>::from_promise(*this)}; }
        std::suspend_always initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void unhandled_exception() { std::terminate(); }
        std::suspend_always yield_value(int val) { value_ = val; return {}; }
        void return_void() {}
    };

    using promise_type = Promise;
    std::coroutine_handle<Promise> h_;

    Generator(std::coroutine_handle<Promise> h) : h_(h) {}
    ~Generator() { if (h_) h_.destroy(); }

    bool next() {
        h_.resume();
        return !h_.done();
    }

    int value() const { return h_.promise().value_; }
};

Generator mySequence() {
    std::cout << "Start\n";
    co_yield 1;
    std::cout << "Middle\n";
    co_yield 2;
    std::cout << "End\n";
}

int main() {
    auto gen = mySequence();
    while (gen.next()) {
        std::cout << "Got: " << gen.value() << "\n";
    }
    return 0;
}

Embedded Applicability: Moderate

  • Stackless coroutines: State is stored in a heap-allocated coroutine frame upon suspension, making memory overhead controllable.
  • Suitable for implementing embedded asynchronous I/O, event loops, state machines, and other patterns, replacing callback hell.
  • Coroutine frames are heap-allocated by default; this can be changed to static memory pools via custom operator new.
  • C++20 only provides the language mechanism and minimal library support. Practical high-level abstractions (like std::generator) require C++23.
  • Compiler support still has known ICEs (Internal Compiler Errors); thorough testing is required for production use.

Compiler Support

GCCClangMSVC
121419.28

See Also


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

v0.7.0-9-g940ec1b · 940ec1b · 2026-07-05