> ## Documentation Index
> Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt
> Use this file to discover all available pages before exploring further.

# C++ Coroutine Function

A coroutine in C++ is a function that can suspend execution to be resumed later, maintaining its local state across suspensions. A function becomes a coroutine implicitly if its body contains at least one of three specific keywords: `co_await`, `co_yield`, or `co_return`. Unlike standard functions, coroutines do not use the standard `return` statement and rely on a compiler-generated state machine to manage execution flow.

## Coroutine Keywords

* **`co_await <expr>`**: Evaluates an awaiter object. Suspends the coroutine's execution *only if* the awaiter's `await_ready()` method returns `false`. If it returns `true`, the coroutine continues execution synchronously without suspending.
* **`co_yield <expr>`**: Syntactic sugar for `co_await promise.yield_value(<expr>)`. Suspends the coroutine and returns a value to the caller, provided the resulting awaiter's `await_ready()` method returns `false`.
* **`co_return <expr>`**: Terminates the coroutine and provides a final return value (or `void`).

## Architectural Components

C++ coroutines are stackless and rely on a tripartite architecture consisting of the Coroutine State, the Promise Object, and the Coroutine Handle.

### 1. Coroutine State

A compiler-generated, typically heap-allocated frame that persists across suspensions. It contains:

* The promise object.
* Copied parameters passed to the coroutine.
* Local variables with a lifetime spanning a suspension point.
* The current execution state (instruction pointer).

### 2. The Promise Type

The promise object is manipulated from *inside* the coroutine. It dictates the coroutine's behavior, such as initialization, termination, and exception handling. The return type of a coroutine must define a nested `promise_type` (or specialize `std::coroutine_traits`).

### 3. The Coroutine Handle

The `std::coroutine_handle<promise_type>` is a non-owning pointer manipulated from *outside* the coroutine. The caller uses it to interact with the suspended coroutine state.

```cpp theme={"dark"}
#include <coroutine>
#include <iostream>
#include <exception>

// 1. The Return Type containing the promise_type
struct MyCoroutineType {
    struct promise_type {
        int current_value;
        
        // Creates the object returned to the caller
        MyCoroutineType get_return_object() { 
            return MyCoroutineType{std::coroutine_handle<promise_type>::from_promise(*this)}; 
        }
        
        // Dictates behavior immediately after invocation
        std::suspend_always initial_suspend() { return {}; }
        
        // Dictates behavior just before destruction
        std::suspend_always final_suspend() noexcept { return {}; }
        
        // Handles co_return
        void return_void() {} 
        
        // Handles co_yield
        std::suspend_always yield_value(int val) { 
            current_value = val;
            return {}; 
        }
        
        // Catches unhandled exceptions inside the coroutine body
        void unhandled_exception() { std::terminate(); }
    };

    std::coroutine_handle<promise_type> handle;
    
    MyCoroutineType(std::coroutine_handle<promise_type> h) : handle(h) {}
    MyCoroutineType(const MyCoroutineType&) = delete;
    MyCoroutineType(MyCoroutineType&& other) noexcept : handle(other.handle) {
        other.handle = nullptr;
    }
    ~MyCoroutineType() { if (handle) handle.destroy(); }
};

// 2. The Coroutine Function
MyCoroutineType example_coroutine(int param) {
    co_await std::suspend_always{}; 
    co_yield param * 2;             
    co_return;                      
}

// 3. The Caller
int main() {
    MyCoroutineType coro = example_coroutine(10);
    
    // Resumes from initial_suspend, executes until co_await
    coro.handle.resume(); 
    
    // Resumes from co_await, executes until co_yield
    coro.handle.resume(); 
    
    std::cout << "Yielded: " << coro.handle.promise().current_value << '\n';
    
    // Resumes from co_yield, executes until co_return and final_suspend
    coro.handle.resume(); 
    
    return 0;
}
```

## The Awaiter Interface

When `co_await <expr>` is evaluated, `<expr>` must resolve to an *Awaitable* object. The compiler interacts with this object via the Awaiter interface to determine exactly how the suspension occurs.

```cpp theme={"dark"}
#include <coroutine>
#include <iostream>
#include <exception>

struct CustomAwaiter {
    // 1. If true, suspension is skipped entirely.
    bool await_ready() const noexcept { 
        return false; 
    }

    // 2. Called immediately after suspension. 
    // Returning void unconditionally suspends the coroutine and returns control to the caller.
    // (Can also return bool to conditionally suspend, or a coroutine_handle to perform a symmetric transfer).
    void await_suspend(std::coroutine_handle<>) const noexcept {
        std::cout << "Coroutine suspended.\n";
    }

    // 3. Called when the coroutine resumes. 
    // The return value becomes the result of the co_await expression.
    int await_resume() const noexcept { 
        return 42; 
    }
};

struct DummyTask {
    struct promise_type {
        DummyTask get_return_object() { 
            return DummyTask{std::coroutine_handle<promise_type>::from_promise(*this)}; 
        }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_always final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() { std::terminate(); }
    };

    std::coroutine_handle<promise_type> handle;

    DummyTask(std::coroutine_handle<promise_type> h) : handle(h) {}
    DummyTask(const DummyTask&) = delete;
    DummyTask(DummyTask&& other) noexcept : handle(other.handle) {
        other.handle = nullptr;
    }
    ~DummyTask() { if (handle) handle.destroy(); }
};

DummyTask awaiter_example() {
    // Suspends execution here and returns control to main.
    int result = co_await CustomAwaiter{};
    
    // Executes after main calls task.handle.resume().
    std::cout << "Awaiter result: " << result << '\n';
    co_return;
}

int main() {
    DummyTask task = awaiter_example();
    
    // Resume the coroutine from the CustomAwaiter suspension point.
    task.handle.resume();
    
    return 0;
}
```

*Note: The standard library provides two trivial awaiters: `std::suspend_always` (always suspends) and `std::suspend_never` (never suspends).*

## Compiler Execution Flow

When a coroutine is invoked, the compiler injects boilerplate to manage the state machine:

1. Allocates the coroutine state using `operator new`.
2. Copies function parameters into the coroutine state.
3. Constructs the `promise_type` object.
4. Calls `promise.get_return_object()`. The result is kept as a local variable to be returned to the caller.
5. Begins an implicit `try-catch` block.
6. Executes `co_await promise.initial_suspend()` *inside* the `try-catch` block.
7. Executes the actual body of the coroutine.
8. If an exception escapes the body or the resume phase of `initial_suspend`, it is caught and routed to `promise.unhandled_exception()`.
9. Upon reaching `co_return` or the end of the body, calls `promise.return_void()` or `promise.return_value()`.
10. Destroys local variables in reverse order of creation.
11. Exits the `try-catch` block.
12. Executes `co_await promise.final_suspend()`.
13. State destruction depends on the behavior of `final_suspend`:
    * If `final_suspend` suspends the coroutine (e.g., returns `std::suspend_always`), the caller or resumer is responsible for calling `.destroy()` on the handle to deallocate the state.
    * If `final_suspend` does not suspend (e.g., returns `std::suspend_never`), the coroutine state is destroyed automatically upon completion. Manually calling `.destroy()` in this scenario results in undefined behavior (a double-free).

## Restrictions

A function cannot be a coroutine if it is:

* A `constexpr` function.
* A constructor or destructor.
* The `main` function.
* A function using standard `return` statements (a coroutine must exclusively use `co_return` if it returns).
* A function with variadic arguments (varargs), such as `void foo(int, ...)`.
* A function with a placeholder return type (`auto` or `decltype(auto)`).

<div
  style={{ 
display: "flex", 
justifyContent: "space-between", 
alignItems: "center", 
maxWidth: "754px", 
padding: "1rem 0",
marginBottom: "24px"
}}
>
  <span style={{ fontWeight: "bold", fontSize: "1.25rem", color: "var(--tw-prose-headings)", fontFamily: "Inter, ui-sans-serif, system-ui, sans-serif" }}>Tired of Poor C++ Skills? Fix That With Deep Grasping!</span>

  <a
    href="https://syntblaze.com"
    target="_blank"
    style={{ 
  marginLeft: "24px",
  textDecoration: "none", 
  backgroundColor: "#007AFF",
  color: "#ffffff", 
  padding: "6px 16px", 
  borderRadius: "16px",
  fontSize: "0.9rem",
  fontWeight: "600",
  textAlign: "center",
  transition: "background-color 0.2s ease"
}}
  >
    Learn More
  </a>
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/skill-tracking.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=b9b0305c93bb501c9e767b5c76c88835" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/skill-tracking.png" />

  <img src="https://mintcdn.com/syntblazellc/23tyuOzaWS88qFlc/images/nuggets.png?fit=max&auto=format&n=23tyuOzaWS88qFlc&q=85&s=c86c80197299762989e9b882419b2109" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/nuggets.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/bite-sized-exercises.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=a65f9a38c37ff28ab73ed783c53c60e3" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/bite-sized-exercises.png" />
</div>

<div style={{ display: "flex", gap: "12px", flexWrap: "wrap", marginTop: "12px" }}>
  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/mastery-chain.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=748a1763454713e679260fbb95f154a2" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/mastery-chain.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-previews.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=242f61448ff5dd6deaaab2dccc13b507" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-previews.png" />

  <img src="https://mintcdn.com/syntblazellc/-L0ums_2lctDSZ1l/images/element-explanations.png?fit=max&auto=format&n=-L0ums_2lctDSZ1l&q=85&s=cf0fc1c31f9cd0fc26716781be05fbc9" style={{ width: "30%", minWidth: 60 }} width="621" height="1344" data-path="images/element-explanations.png" />
</div>
