CodeBlanks Logo Icon CodeBlanks

What are coroutines?

Learn the C++20 coroutine concept.

What are coroutines?

A coroutine is a function that can be suspended and resumed. It entered the standard library with C++20. A normal function runs from start to end; a coroutine can pause at intermediate points and be resumed from outside.

Three keywords define a coroutine: co_await (await point), co_yield (produce a value) and co_return (finish). If a function uses any of these, it automatically becomes a coroutine. Coroutines let us write asynchronous operations, generators and state machines in a clean way.

Suspend and resume

A coroutine creates a coroutine frame when called. This frame stores local variables and state on the heap. When the function suspends, the frame stays; when resumed, it continues from the same state.

The return type of a coroutine must be a type that contains a promise_type. This type defines how the coroutine starts, finishes and returns a value. With std::coroutine_handle you manually resume or destroy the coroutine. This mechanism manages asynchronous flows in a type-safe way.

Practice Return a value with co_return

Write co_return 42; in the body of the make_value coroutine. In main get the value with promise().value_ from the result of make_value() and print it with std::cout.

Starter code

main.cpp
#include <iostream>
#include <coroutine>

struct Returner {
    struct promise_type {
        int value_;
        Returner get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_value(int v) { value_ = v; }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Returner make_value() {
    // Return 42 with co_return
}

int main() {
    // Call make_value and print the value
    return 0;
}

Sample solution

main.cpp
#include <iostream>
#include <coroutine>

struct Returner {
    struct promise_type {
        int value_;
        Returner get_return_object() { return {std::coroutine_handle<promise_type>::from_promise(*this)}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_value(int v) { value_ = v; }
        void unhandled_exception() { }
    };
    std::coroutine_handle<promise_type> handle;
};

Returner make_value() {
    co_return 42;
}

int main() {
    auto r = make_value();
    std::cout << r.handle.promise().value_;
    return 0;
}

Expected output

42

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What is the difference between a coroutine and a normal function?

  • A coroutine runs faster
  • A coroutine can only be defined inside a class
  • A coroutine can be suspended and resumed Correct answer
  • A coroutine takes no parameters

Explanation: A coroutine is a function that can be suspended and resumed.

2 the coroutine keyword

Question
Task run() { ____ 42; }
Answer
Task run() { co_return 42; }

Explanation: co_return finishes the coroutine and returns a value.

3 Match each piece to its role

Term Meaning
co_await Await point
co_yield Produce a value
co_return Finish
promise_type Behaviour contract

All lessons in Advanced