# Vad är coroutines i C++

25 december 2025 | https://www.ribomation.se/blog/2025/vad-ar-coroutines-i-c++/

Coroutines i C++20 ger dig ett språkstöd för kooperativ multitasking: funktioner som kan pausa och återupptas utan att du behöver bygga ett eget state machine-ramverk. I den här guiden bygger vi en minimal coroutine-“runtime” från grunden och visar hur de centrala byggstenarna (promise\_type, coroutine\_handle och awaiters) hänger ihop. Därefter går vi igenom fyra praktiska mönster: en task som kan stegas, en producer som returnerar ett slutresultat, en generator som yield:ar värden, samt en iterator variant av generator som kan användas i foreach-loopar.

Ett första inledande exempel
----------------------------

Här följer ett komplett körbart exempel på en task coroutine. I de följande avsnitten går jag igenom de olika delarna och hur de hänger ihop. Tankegången här är att du ser all programkod, så att du kan orientera dig i API beskrivningen som sedan följer.

```cpp
#include <print>
#include <coroutine>

struct Suspend {
    constexpr bool await_ready() const noexcept { return false; }
    constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
    constexpr void await_resume() const noexcept {}
};

struct [[nodiscard]] TaskCoroutine {
    struct promise_type;
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    TaskCoroutine(handle_type h) : handle{h} {}
    ~TaskCoroutine() { if (handle) handle.destroy(); }

    bool has_more() {
        if (not handle || handle.done()) return false;
        handle.resume();
        return not handle.done();
    }

    TaskCoroutine(TaskCoroutine const&) = delete;
    TaskCoroutine(TaskCoroutine &&) noexcept = delete;
    auto operator=(TaskCoroutine const&) -> TaskCoroutine& = delete;
    auto operator=(TaskCoroutine &&) noexcept -> TaskCoroutine& = delete;
};

struct TaskCoroutine::promise_type {
    auto get_return_object() {
        std::println("      [promise] get_return_object");
        return TaskCoroutine{ handle_type::from_promise(*this) };
    }
    auto initial_suspend() noexcept {
        std::println("      [promise] initial_suspend");
        return Suspend{};
    }
    auto final_suspend() noexcept {
        std::println("      [promise] final_suspend");
        return Suspend{};
    }
    void return_void() {
        std::println("      [promise] return_void");
    }
    void unhandled_exception() { std::terminate(); }
};

auto SimpleTask(unsigned n) -> TaskCoroutine {
    std::println("      [coro] start");
    for (auto k = 1U; k <= n; ++k) {
        std::println("      [coro] {} / {} suspend", k, n);
        co_await Suspend{};
        std::println("      [coro] resumed");
    }
    std::println("      [coro] done");
}

int main() {
    std::println("[main] enter");
    auto t = SimpleTask(3);
    std::println("[main] task created");
    for (auto j = 1U; t.has_more(); ++j) {
        std::println("[main] loop {}", j);
    }
    std::println("[main] exit");
}
```

I programkoden ovan har vi, räknat uppifrån och ned:

*   `Suspend` - Ett suspenderings-objekt, mer formellt ett _awaiter_ objekt.
*   `TaskCoroutine` - Ett coroutine-interface innehållande ett handtag till dess inre state och en funktion som väcker upp den så länge det finns mer data.
*   `TaskCoroutine::promise_type` - En promise-type klass, som representerar dess inre state.
*   `SimpleTask` - Själva coroutine definitionen.
*   `main` - Huvudprogrammet där vi skapar och anropar task objektet.

Kompilerar vi och kör programmet kan det se ut så här:

```shell
C++> g++ -std=c++23 -Wall ../simple-task.cxx -o task
C++> ./task 
[main] enter
      [promise] get_return_object
      [promise] initial_suspend
[main] task created
      [coro] start
      [coro] 1 / 3 suspend
[main] loop 1
      [coro] resumed
      [coro] 2 / 3 suspend
[main] loop 2
      [coro] resumed
      [coro] 3 / 3 suspend
[main] loop 3
      [coro] resumed
      [coro] done
      [promise] return_void
      [promise] final_suspend
[main] exit
C++> 
```

Jag har indenterat utskrifterna från coroutine objektet, så att man tydligt ser hur kontrollen flyttas från `main` till coroutine objektet och sen tillbaka. Detta upprepas tills det är färdigt.

> Observera att vi pratar om C++20 coroutines i denna artikel, men jag kompilerar med C++23, eftersom jag gillar att kunna använda `std::println()` för utskrifterna.

Coroutine API
-------------

I detta avsnitt sammanfattar jag de viktigaste delarna av C++ coroutines API för enkel referens senare i artikeln och eventuella efterföljande artiklar om coroutines.

### Coroutine Body

Trist nog så har man valt att inte införa någon ny syntax eller reserverat ord för att deklarera en coroutine, utan det sker på ett litet mer subtilt sätt. En (_vanlig_) funktion som innehåller något eller några av följande nya reserverade ord är hux flux en coroutine.

*   `co_await`
*   `co_yield`
*   `co_return`

Så, enklast tänkbara coroutine (som förvisso inte gör någonting alls) ser ut så här:

```cpp
auto MyCoroutine() -> MyCoroutineInterface {
    co_return;
}

int main() {
    MyCoroutineInterface coro = MyCoroutine();
}
```

### Coroutine Interface

En struct/klass blir ett coroutine-interface om den innehåller en medlemstyp med namnet `promise_type` och ett medlems-objekt av typen `std::coroutine_handle<T>`. Den förstnämnda representerar det interna tillståndet för en coroutine och den senare utgör en kapsel för den förstnämnda och _handtag_ för applikations-koden. Både dessa diskuterar jag igenom i följande avsnitt.

Namnet på en dylik struct är valfritt, men vanligtvis har namnet ett suffix med någon av följande:

*   _Xyz_Coroutine
*   _Xyz_CoroutineInterface
*   _Xyz_Coro

Det rekommenderas att annotera klassen med `[[nodiscard]]`, vilket innebär att objekt av denna typ inte kan ignoreras av misstag, utan behöver tilldelas till en variabel, för senare bruk.

Vidare, så bör copy-members annoteras med `delete` för att undvika att kopiera ett coroutine objekt, vilket kan leda till odefinierat beteende. Om man inte deklarerar move-members, så blir även dessa implicit markerade med `delete`. Önskar man move-semantics, så går det förvisso bra att implementera dessa.

```cpp
struct [[nodiscard]] MyCoroutineInterface {
    struct MyPromiseType; //forward decl
    using promise_type = MyPromiseType;
    using handle_type  = std::coroutine_handle<promise_type>;
    
    handle_type handle;
    MyCoroutineInterface(handle_type h) : handle(h) {}
    ~MyCoroutineInterface() { handle.destroy(); }
    
    MyCoroutineInterface(MyCoroutineInterface const&) = delete;
    auto operator=(MyCoroutineInterface const&) -> MyCoroutineInterface& = delete;
    MyCoroutineInterface(MyCoroutineInterface &&) = delete;
    auto operator=(MyCoroutineInterface &&) -> MyCoroutineInterface& = delete;
    //...
};

struct MyCoroutineInterface::MyPromiseType {
    //...
};
```

### Coroutine Handle

Det interna tillståndet för en coroutine kapslas in i en `std::coroutine_handle<PromiseType>`. Ett objekt av denna, utgör gränsyta för att interagera med en coroutine från applikationen. I tabellen nedan visar jag det viktigaste funktionerna du bör känna till.

Name

Returns

Parameters

Description

`from_promise` (_static_)

`coroutine_handle`

_PromiseType_&

Creates a coroutine\_handle from the promise object of a coroutine.

`promise`

_PromiseType_&

\-

Obtains a reference to the promise object.

`from_address` (_static_)

`coroutine_handle`

`void*`

Creates a coroutine\_handle from an underlying address of another coroutine\_handle.

`address`

`void*`

\-

Returns the underlying address of the coroutine\_handle.

`resume`

\-

\-

Resumes the execution of the coroutine.

`operator()`

\-

\-

_Same as above_

`operator bool`

`bool`

\-

Returns true if active. Same as _address() != nullptr_

`done`

`bool`

\-

Returns true if completed (i.e., at its final suspend point)

`destroy`

\-

\-

Destroys the coroutine state of the coroutine

### Promise Type

Varje coroutine-interface klass, måste ha en medlemstyp med det fixerade namnet `promise_type`. Detta kan vara en nästlad struct, eller ett typalias till en struct definierad på annan plats. Uppgiften för en promise-type är att hantera _state_, samt emitterade värden och/eller returnerat värde.

En källa till ständig irritation är att det finns ingen klass att använda eller ärva från eller dylikt. Man måste implementera en promise-type själv och missar man något så gnäller kompilatorn tjurigt. I tabellen nedan visar jag de viktigaste funktionerna du behöver känna till för att implementera en promise-type.

Name

Returns

Parameters

Description

`get_return_object`

_CoroutineInterface_

\-

Initializes a coroutine\_handle to the coroutine.

`initial_suspend`

_awaiter_

\-

Determines whether the coroutine should be suspended at its initial suspend point.

`final_suspend`

_awaiter_

\-

Determines whether the coroutine should be suspended at its final suspend point.

`yield_value`

_awaiter_

_T_

Yields a value from the coroutine, via `co_yield` _expr_.

`return_value`

\-

_T_

Returns a final value from the coroutine, via `co_return` _expr_.

`return_void`

\-

\-

Used when the coroutine returns nothing, or uses a plain `co_return`.

`unhandled_exception`

\-

\-

Handles an exception in the coroutine, that should be propagated to the caller.

#### get\_return\_object

Funktionen `get_return_object` har som uppgift att skapa (och returnera) ett coroutine-interface objekt, vilket sen används av applikations-koden. Koden i funktionen ser i regel ut på följande vis:

```cpp
auto get_return_object() -> CoroutineInterface {
    auto handle    = CoroutineHandle::from_promise(*this);
    auto interface = CoroutineInterface{handle};
    return interface;
}
```

Oftast kan koden kortas ned till en one-liner, på följande vis:

```cpp
auto get_return_object() {
    return CoroutineInterface{ CoroutineHandle::from_promise(*this) };
}
```

Om konstruktorn till coroutine-interface klassen tar ett handle objekt och inte märkt med `explicit`, så räcker det med att returnera handle objektet:

```cpp
struct CoroutineInterface {
    struct MyPromiseType {
        auto get_return_object() { return handle_type::from_promise(*this); }
        //...
    };
    
    using promise_type = MyPromiseType;
    using handle_type  = std::coroutine_handle<MyPromiseType>;
    handle_type handle;
    
    CoroutineInterface(handle_type h) : handle(h) {}
    //...
};
```

#### initial\_suspend & final\_suspend

Dessa två funktioner anropas i var sin ände av livs-cykeln för en coroutine. Den första direkt efter att coroutine-objektet skapats och avgör huruvida coroutine-objektet ska starta med att pausa eller inte. Den andra direkt innan coroutine-objektet avslutas, och avgör huruvida coroutine-objektet ska pausa eller inte innan det avslutas. initial\_suspend kan användas för att utföra initialisering, och final\_suspend kan användas för att utföra rensning eller avslutningsåtgärder.

Båda returnerar ett så kallat _awaiter_ objekt, vilken signalerar till runtime-systemet hur det ska fortsätta. Detta objekt kan också konfigureras för att styra hur coroutine-objektet ska bete sig vid paus och återupptagning.

#### return\_value vs. return\_void

Beroende på om coroutine objektet ska returnera ett sista värde eller inte, så ska en av dessa return funktioner implementeras. Det blir ett kompileringsfel om båda är definierade.

Implementera `return_void` om coroutine-objektet inte ska returnera något sista värde. I de flesta fall gör den ingenting alls, utan fungerar som ett tips till kompilatorn att coroutine-objektet inte ska returnera något sista värde. För coroutine objektet, så kan den anropa `co_return` eller helt enkelt smita ut via sista klammerparentes. Båda varianterna betyder samma sak.

Implementera `return_value` om coroutine-objektet ska returnera ett sista värde. Detta innebär i regel följande:

1.  Deklarera en variabel i promise klassen, med önskad typ
2.  Låt return\_value ta en parameter av denna typ och tilldela till variabeln ovan
3.  Deklarera en publik funktion som returnerar värdet av denna variabel (obs inte en referens eller pekare)
4.  Säkerställ att coroutine-objektet anropar `co_return` _expr_, där _expr_ är av korrekt typ.

```cpp
struct MyPromiseType {
    //...
    int returned_value;
    void return_value(int v) { returned_value = v; }
};

struct MyCoroutineInterface {
    //...
    handle_type h;
    int get_final_value() const { return h.promise().returned_value; }
};

auto Task() -> MyCoroutineInterface {
    //...
    co_return 42;
}

int main() {
    auto t = Task();
    //...
    auto v = t.get_final_value();
}
```

#### yield\_value

Denna funktion hanterar emittering av ett värde via `co_yield`\-instruktionen. Den tar ett argument av önskad typ och returnerar ett _awaiter_ objekt som används för att styra paus och återupptagning av coroutine-objektet. Precis som för returvärdet, så behövs en variabel i promise objektet. Skillnaden är att denna uppdateras varje gång co\_yield anropas.

```cpp
struct MyPromiseType {
    //...
    int yielded_value;
    auto yield_value(int v) { yielded_value = v; return SuspendAwaiter{}; }
};

struct MyCoroutineInterface {
    //...
    handle_type h;
    int get_current_value() const { return h.promise().yielded_value; }
};

auto Task() -> MyCoroutineInterface {
    //...
    co_yield 42;
    //...
}

int main() {
    auto t = Task();
    //...
    auto v = t.get_current_value();
    //...
}
```

### Awaiter

Ett _awaiter_ objekt är en liten hjälpklass som används för att styra paus och återupptagning av en coroutine. Awaiter objekt returneras från funktioner som `initial_suspend`, `final_suspend` och `yield_value` i promise-type klassen. De kan också användas tillsammans med `co_await` operatorn.

Ett awaiter objekt måste implementera tre specifika funktioner som runtime-systemet anropar vid olika tillfällen. Precis som för promise\_type, måste man själv hålla reda på funktionernas namn och parametrar.

Name

Returns

Parameters

Description

`await_ready`

`bool`

\-

Returns true if the coroutine should continue without suspending.

`await_suspend`

`void`

`coroutine_handle<>`

Called when the coroutine is about to suspend. Can be used to schedule work.

`await_resume`

_T_

\-

Called when the coroutine resumes. The return value becomes the result of co\_await.

Här följer en mycket enkel awaiter, som signallerar att en coroutine ska suspenderas:

```cpp
struct SuspendAwaiter {
    constexpr bool await_ready() const noexcept { return false; }
    constexpr void await_suspend(std::coroutine_handle<>) const noexcept {}
    constexpr void await_resume() const noexcept {}
};

struct XyzCoroutine::promise_type {
    //...
    auto initial_suspend() noexcept { return SuspendAwaiter{}; }
}
```

Standardbiblioteket tillhandahåller två färdiga awaiter-typer, så man inte behöver skriva klassen ovan själv.

```cpp
namespace std {
    struct suspend_always {
        constexpr bool await_ready() const noexcept { return false; }
        constexpr void await_suspend(coroutine_handle<>) const noexcept { }
        constexpr void await_resume() const noexcept { }
    };
    struct suspend_never {
        constexpr bool await_ready() const noexcept { return true; }
        constexpr void await_suspend(coroutine_handle<>) const noexcept { }
        constexpr void await_resume() const noexcept { }
    };
}
//...
struct XyzCoroutine::promise_type {
    //...
    auto initial_suspend() noexcept { return std::suspend_always{}; }
}
```

### Deklarationsordning av promise och interface typer

Som du säkert redan noterat, så finns det ett cirkulärt beroende mellan promise- och interface typerna. Promise typerna är de som definierar hur en coroutine fungerar, medan interface typerna är de som används för att interagera med coroutines. Detta innebär att promise typerna måste definieras innan interface typerna kan användas, vilket kan leda till kompilatorfel om ordningen inte är korrekt. Det finns några olika varianter för hur de kan deklareras, vilka jag listar här nedan.

#### Variant 1

Forward deklarera promise-type, deklarera typalias för handle-type, samt definiera promise-type klassen.

```cpp
struct XyzCoroutine {
    struct promise_type; //forward decl
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    XyzCoroutine(handle_type h) : handle(h) {}
    ~XyzCoroutine() { handle.destroy(); }
    
    struct promise_type {
        auto get_return_object() {
            return XyzCoroutine{ handle_type::from_promise(*this) };
        }
        //...
    };
    //...
};
```

#### Variant 2

Forward deklarera promise-type, deklarera typalias för handle-type, samt definiera promise-type klassen nedanför interface klassen.

```cpp
struct XyzCoroutine {
    struct promise_type; //forward decl
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    XyzCoroutine(handle_type h) : handle(h) {}
    ~XyzCoroutine() { handle.destroy(); }
    //...
};

struct XyzCoroutine::promise_type {
    auto get_return_object() {
        return XyzCoroutine{ handle_type::from_promise(*this) };
    }
    //...
};
```

#### Variant 3

Definiera promise-type först och sen deklarera handle.

```cpp
struct XyzCoroutine {
    struct promise_type {
        auto get_return_object() {
            return std::coroutine_handle<promise_type>::from_promise(*this);
        }
        //...
    };
  private:
    std::coroutine_handle<promise_type> handle;
  public:
    XyzCoroutine(std::coroutine_handle<promise_type> h) : handle(h) {}
    ~XyzCoroutine() { handle.destroy(); }
};
```

#### Variant 4

Definiera promise-type som en generiskt template typ och använd den i interface klassen.

```cpp
template<typename CoroInterface>
struct GenericPromise {
    auto get_return_object() {
        return std::coroutine_handle< GenericPromise<CoroInterface> >::from_promise(*this);
    }
    //...
};

struct XyzCoroutine {
    using promise_type = GenericPromise<XyzCoroutine>;
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    XyzCoroutine(handle_type h) : handle(h) {}
    ~XyzCoroutine() { handle.destroy(); }
    //...
};
```

### Validering av handle\_type

I coroutine destruktorn brukar man testa för att den är aktiv och om så är fallet anropa `destroy()`.

```cpp
//...
handle_type handle;
XyzCoro(handle_type h) : handle{h} {}
~XyzCoro {
    if (handle) handle.destroy();
}
```

Det som anropas i destruktorn är `operator bool()`, så det ser egentligen ut på följande sätt:

```cpp
//...
~XyzCoro {
    if (handle.operator bool()) handle.destroy();
}
```

Denna boolska operator, testar om det finns ett coroutine objekt eller inte. Det vill säga det ser egentligen ut på följande sätt:

```cpp
//...
~XyzCoro {
    if (handle.address() != nullptr) handle.destroy();
}
```

På liknande sätt kan vi översätta vad som sker i `has_more()` funktionen:

```cpp
 bool has_more() {
    if (not handle || handle.done()) return false;
    //...
}        
```

```cpp
 bool has_more() {
    if (not handle.operator bool() || handle.done()) return false;
    //...
}        
```

```cpp
 bool has_more() {
    if (not (handle.address() != nullptr)) || handle.done()) return false;
    //...
}        
```

```cpp
 bool has_more() {
    if (handle.address() == nullptr) || handle.done()) return false;
    //...
}        
```

### När anropas promise-type funktionerna?

Om vi går tillbaka till vår task coroutine, som såg ut så här, när utskrifterna är borttagna:

```cpp
auto SimpleTask(unsigned n) -> TaskCoroutine {
    for (auto k = 1U; k <= n; ++k) {
        co_await std::suspend_always{};
    }
    co_return;
}
```

Kompilatorn å andra sidan, kommer att betrakta denna funktion på följande (_förenklade_) sätt:

```cpp
auto SimpleTask(unsigned n) -> TaskCoroutine {
    auto p = TaskCoroutine::promise_type{};
    auto coro = p.get_return_object();
    co_await p.initial_suspend();
    try {
        for (auto k = 1U; k <= n; ++k) {
            co_await std::suspend_always{};
        }
        p.return_void();
    } catch(...) {
        p.unhandled_exception();
    }
    co_await p.final_suspend();
}
```

Det är givetvis mer som händer bakom kulisserna, såsom att coro objektet ska föras över till anroparen, dvs `main` i vårt exempel. Men översättningen här ovan förmedlar en känsla för när respektive callback funktion i promise-type anropas.

### Hur anropas funktionerna i en awaiter?

Givet att vi en programrad som ser ut som följande:

```cpp
co_await std::suspend_always{};
```

Detta översätt till följande kodfragment:

```cpp
auto&& a = std::suspend_always{};
if (not a.await_ready()) {
    a.await_suspend(std::coroutine_handle<>{/* current coroutine */});
    //leave coro -->
}
// --> back again
a.await_resume(); 
```

Simple Producer
---------------

En _producer_ beräknar ett slutresultat, som sedan skickas ut via `co_return`. Så här ser en enkel sådan ut, som summerar loop-variabeln och returnerar på slutet.

```cpp
#include <print>
#include <coroutine>

struct [[nodiscard]] ProducerCoroutine {
    struct promise_type {
        auto get_return_object() {
            return ProducerCoroutine{ handle_type::from_promise(*this) };
        }
         auto initial_suspend() noexcept { return std::suspend_always{}; }
         auto final_suspend()   noexcept { return std::suspend_always{}; }
         void unhandled_exception() {}

        unsigned returned_value = 0;
        void return_value(unsigned value) { returned_value = value; }
    };
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    ProducerCoroutine(handle_type h) : handle{h} {}
    ~ProducerCoroutine() { if (handle) handle.destroy(); }

    bool has_more() {
        if (not handle || handle.done()) return false;
        handle.resume();
        return not handle.done();
    }
    auto get_result() const {
        return handle.promise().returned_value;
    }

    ProducerCoroutine(ProducerCoroutine const&) = delete;
    auto operator=(ProducerCoroutine const&) -> ProducerCoroutine& = delete;
};

auto Producer(unsigned n) -> ProducerCoroutine {
    std::println("      [coro] start");
    auto sum = 0U;
    for (auto k = 1U; k <= n; ++k) {
        std::println("      [coro] {} / {} suspend", k, n);
        sum += k;
        co_await std::suspend_always{};
        std::println("      [coro] resumed");
    }
    std::println("      [coro] done");
    co_return sum;
}

int main() {
    std::println("[main] enter");
    auto p = Producer(3);
    std::println("[main] producer created");
    for (auto j = 1U; p.has_more(); ++j) {
        std::println("[main] loop {}", j);
    }
    std::println("[main] exit: sum={}", p.get_result());
}
```

Kompilerar och kör vi programmet kan det se ut så här:

```shell
C++> g++ -std=c++23 -Wall ../simple-producer.cxx -o producer
C++> ./producer 
[main] enter
[main] producer created
      [coro] start
      [coro] 1 / 3 suspend
[main] loop 1
      [coro] resumed
      [coro] 2 / 3 suspend
[main] loop 2
      [coro] resumed
      [coro] 3 / 3 suspend
[main] loop 3
      [coro] resumed
      [coro] done
[main] exit: sum=6
C++>
```

Simple Generator
----------------

En _generator_ returnerar värden löpande via `co_yield`. Precis som för producer behövs en variabel som håller aktuellt värde. Denna tilldelas via API funktionen `yield_value`. Sen behöver man en applikations funktion som returnerar detta värde, på liknande sätt som för en producer.

```cpp
#include <print>
#include <coroutine>

struct [[nodiscard]] GeneratorCoroutine {
    struct promise_type {
        auto get_return_object() {
            return GeneratorCoroutine{ handle_type::from_promise(*this) };
        }
        static auto initial_suspend() noexcept { return std::suspend_always{}; }
        static auto final_suspend()   noexcept { return std::suspend_always{}; }
        static void unhandled_exception() {}
        static void return_void() {}

        unsigned yielded_value = 0;
        auto yield_value(unsigned value) {
            yielded_value = value;
            return std::suspend_always{};
        }
    };
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    GeneratorCoroutine(handle_type h) : handle{h} {}
    ~GeneratorCoroutine() { if (handle) handle.destroy(); }

    bool has_more() {
        if (not handle || handle.done()) return false;
        handle.resume();
        return not handle.done();
    }
    auto get_current_value() const {
        return handle.promise().yielded_value;
    }

    GeneratorCoroutine(GeneratorCoroutine const&) = delete;
    auto operator=(GeneratorCoroutine const&) -> GeneratorCoroutine& = delete;
};

auto Generator(unsigned n) -> GeneratorCoroutine {
    std::println("      [coro] start");
    for (auto k = 1U; k <= n; ++k) {
        std::println("      [coro] {} / {} suspend", k, n);
        co_yield k;
        std::println("      [coro] resumed");
    }
    std::println("      [coro] done");
}

int main() {
    std::println("[main] enter");
    auto g = Generator(3);
    std::println("[main] generator created");
    while (g.has_more()) {
        std::println("[main] loop value={}", g.get_current_value());
    }
    std::println("[main] exit");
}
```

Så här kan det se ut om vi kompilerar och kör programmet:

```shell
C++> g++ -std=c++23 -Wall ../simple-generator.cxx -o generator
C++> ./generator 
[main] enter
[main] generator created
      [coro] start
      [coro] 1 / 3 suspend
[main] loop value=1
      [coro] resumed
      [coro] 2 / 3 suspend
[main] loop value=2
      [coro] resumed
      [coro] 3 / 3 suspend
[main] loop value=3
      [coro] resumed
      [coro] done
[main] exit
C++>
```

Simple Iterator
---------------

Det senaste exemplet kan vidareutvecklas lite till, så att den kan fungera i en vanlig iterator-kontext. Det som behövs är en nästlad iterator-klass, som kontrollerar coroutine objektet. Här kommer ett förslag på hur det kan se ut:

```cpp
#include <coroutine>
#include <iterator>
#include <print>
#include <utility>

struct [[nodiscard]] IteratorCoroutine {
    struct promise_type {
        auto get_return_object() {
            return IteratorCoroutine{ handle_type::from_promise(*this) };
        }
        static auto initial_suspend() noexcept { return std::suspend_always{}; }
        static auto final_suspend()   noexcept { return std::suspend_always{}; }
        static void unhandled_exception() {}
        static void return_void() {}

        unsigned yielded_value = 0;
        auto yield_value(unsigned value) {
            yielded_value = value;
            return std::suspend_always{};
        }
    };
    using handle_type = std::coroutine_handle<promise_type>;
  private:
    handle_type handle;
  public:
    IteratorCoroutine(handle_type h) : handle{h} {}
    ~IteratorCoroutine() { if (handle) handle.destroy(); }
    IteratorCoroutine(IteratorCoroutine const&) = delete;
    auto operator=(IteratorCoroutine const&) -> IteratorCoroutine& = delete;

    struct Iterator {
        handle_type coroutine;
        Iterator(handle_type h_) : coroutine{h_} {}
        void operator++() { coroutine.resume(); }
        auto operator*() const {
            return coroutine.promise().yielded_value;
        }
        bool operator==(std::default_sentinel_t) const {
            return not coroutine || coroutine.done();
        }
    };

    auto begin() -> Iterator {
        if (handle) handle.resume();
        return Iterator{handle};
    }
    auto end() { return std::default_sentinel_t{}; }
};

auto Iterator(unsigned n) -> IteratorCoroutine {
    std::println("      [coro] start");
    for (auto k = 1U; k <= n; ++k) {
        std::println("      [coro] {} / {} suspend", k, n);
        co_yield k;
        std::println("      [coro] resumed");
    }
    std::println("      [coro] done");
}

int main() {
    std::println("[main] enter");
    usecase_while();
    usecase_foreach();
    usecase_fibonacci();
    std::println("[main] exit");
}
```

Funktionen `main` anropar tre användningsfall (usecase). Vi tar dem i tur och ordning, med funktionen följt av dess utdata.

### Användningsfall: while

I detta första fall gör vi allting explicit, genom att skapa coroutine objektet, via den erhålla ett iterator objekt och iterera tills det tar slut och i varje varv hämta ut aktuellt värde.

```cpp
void usecase_while() {
    std::println("-- while-loop --");
    auto coro = Iterator(3);
    auto iter = coro.begin();
    std::println("[main] iterator created");
    while (iter != coro.end()) {
        auto value = *iter;
        std::println("[main] value={}", value);
        ++iter;
    }
}
```

```shell
-- while-loop --
      [coro] start
      [coro] 1 / 3 suspend
[main] iterator created
[main] value=1
      [coro] resumed
      [coro] 2 / 3 suspend
[main] value=2
      [coro] resumed
      [coro] 3 / 3 suspend
[main] value=3
      [coro] resumed
      [coro] done
```

### Användningsfall: foreach

I detta fall, använder vi foreach-loopen (_range-based for-loop_), som sköter alla mellanliggande ting.

```cpp
void usecase_foreach() {
    std::println("-- foreach-loop --");
    for (auto k: Iterator(3)) std::println("[main] value={}", k);
}
```

```shell
-- foreach-loop --
      [coro] start
      [coro] 1 / 3 suspend
[main] value=1
      [coro] resumed
      [coro] 2 / 3 suspend
[main] value=2
      [coro] resumed
      [coro] 3 / 3 suspend
[main] value=3
      [coro] resumed
      [coro] done
```

Som synes, får vi precis samma utskrift som i föregående användningsfall.

### Användningsfall: fibonacci

Till sist, visar jag hur man kan låta en lambda bli en coroutine. Detta fungerar eftersom en lambda översätts till en struct med en function-call operator, vilket är en vanlig funktion.

```cpp
void usecase_fibonacci() {
    std::println("-- fibonacci --");
    auto fib = [](unsigned N) -> IteratorCoroutine {
        std::println("      [coro] start");
        auto f1 = 1U;
        auto f2 = 1U;
        for (auto k = 1U; k <= N; ++k) {
            std::println("      [coro] emit {}", f1);
            co_yield f1;
            f1 = std::exchange(f2, f1+f2);
        }
        std::println("      [coro] done");
    };
    for (auto k : fib(10)) std::println("[main] {}", k);
}
```

```shell
-- fibonacci --
      [coro] start
      [coro] emit 1
[main] 1
      [coro] emit 1
[main] 1
      [coro] emit 2
[main] 2
      [coro] emit 3
[main] 3
      [coro] emit 5
[main] 5
      [coro] emit 8
[main] 8
      [coro] emit 13
[main] 13
      [coro] emit 21
[main] 21
      [coro] emit 34
[main] 34
      [coro] emit 55
[main] 55
      [coro] done
```

Sammanfattning
--------------

C++20-coroutines är ett språkstöd för funktioner som kan pausa och återupptas, vilket gör det möjligt att skriva asynkrona och stegvisa flöden utan att manuellt bygga state machines. Artikeln visar hur en coroutine delas upp i ett “interface” (returtypen), ett “body” (själva funktionen med co\_await/co\_yield/co\_return) och en promise\_type som fungerar som bryggan mellan dem. Du får en konkret genomgång av std::coroutine\_handle, hur initial\_suspend och final\_suspend styr när exekveringen startar och avslutas, samt hur en awaiter fungerar via await\_ready, await\_suspend och await\_resume. Avslutningsvis byggs och jämförs ett antal olika praktiska coroutine idiom, vilka du kan använda som utgångspunkt för din egen kod.
