# std::coroutine_handle

< cpp‎ | coroutine

定义于头文件 `<coroutine>` |  |
template< class Promise = void > struct coroutine_handle; | (1) | (C++20 起)
template<> struct coroutine_handle<void>; | (2) | (C++20 起)
template<> struct coroutine_handle<std::noop_coroutine_promise>; | (3) | (C++20 起)
using noop_coroutine_handle = std::coroutine_handle<std::noop_coroutine_promise>; | (4) | (C++20 起)

类模板 `coroutine_handle` 能用于指代暂停或执行的协程。 `coroutine_handle` 的每个特化均为字面类型 (LiteralType) 。

1) 主模板，可从 `Promise` 类型的承诺对象创建。
2) 特化 std::coroutine_handle<void> 擦除承诺类型。它可从其他特化转换。
3) 特化 std::coroutine_handle<std::noop_coroutine_promise> 指代无操作协程。不能从承诺对象创建它。

典型实现上， std::coroutine_handle 的每个特化均为可平凡复制 (TriviallyCopyable) ，并保有一个指向协程状态的指针作为其仅有的非静态成员。

添加 `coroutine_handle` 的特化的程序行为未定义。

### 成员函数

(构造函数) (C++20) | 构造 `coroutine_handle` 对象 (公开成员函数)
operator= (C++20) | 赋值 `coroutine_handle` 对象 (公开成员函数)
from_promise [静态] (C++20) | 从协程的承诺对象创建 `coroutine_handle` (公开静态成员函数)
##### 转换
operator coroutine_handle<> (C++20) | 获得擦除类型的 `coroutine_handle` (公开成员函数)
##### 观察器
done (C++20) | 检查协程是否已完成 (公开成员函数)
operator bool (C++20) | 检查柄是否表示协程 (公开成员函数)
##### 控制
operator()resume (C++20) | 恢复协程执行 (公开成员函数)
destroy (C++20) | 销毁协程 (公开成员函数)
##### 承诺访问
promise (C++20) | 访问协程的承诺对象 (公开成员函数)
##### 导出/导入
address (C++20) | 导出底层地址，即支撑协程的指针 (公开成员函数)
from_address [静态] (C++20) | 从指针导入协程 (公开静态成员函数)

### 非成员函数

operator==operator<=> (C++20) | 比较二个 `coroutine_handle` 对象 (函数)

### 辅助类

std::hash<std::coroutine_handle> (C++20) | std::coroutine_handle 的散列支持 (类模板特化)

### 注解

`coroutine_handle` 可能悬垂，该情况下必须谨慎使用该 `coroutine_handle` 以避免未定义行为。

### 示例

    #include <coroutine>
    #include <iostream>
    #include <optional>
    #include <ranges>

    template<typename T> requires std::movable<T>
    class Generator {
    public:
        struct promise_type {
            Generator<T> get_return_object() {
                return Generator{Handle::from_promise(*this)};
            }
            static std::suspend_always initial_suspend() noexcept {
                return {};
            }
            static std::suspend_always final_suspend() noexcept {
                return {};
            }
            std::suspend_always yield_value(T value) noexcept {
                current_value = std::move(value);
                return {};
            }
            // 生成器协程中不允许 co_await 。
            void await_transform() = delete;
            static void unhandled_exception() {
                throw;
            }

            std::optional<T> current_value;
        };

        using Handle = std::coroutine_handle<promise_type>;

        explicit Generator(Handle coroutine) :
            m_coroutine{coroutine}
        {}

        Generator() = default;
        ~Generator() {
            if (m_coroutine) {
                m_coroutine.destroy();
            }
        }

        Generator(const Generator&) = delete;
        Generator& operator=(const Generator&) = delete;

        Generator(Generator&& other) noexcept :
            m_coroutine{other.m_coroutine}
        {
            other.m_coroutine = {};
        }

        Generator& operator=(Generator&& other) noexcept {
            if (this != &other) {
                m_coroutine = other.m_coroutine;
                other.m_coroutine = {};
            }
            return *this;
        }

        // 基于范围的 for 循环支持。
        class Iter {
        public:
            void operator++() {
                m_coroutine.resume();
            }
            const T& operator*() const {
                return *m_coroutine.promise().current_value;
            }
            bool operator==(std::default_sentinel_t) const {
                return !m_coroutine || m_coroutine.done();
            }

            explicit Iter(Handle coroutine) :
                m_coroutine{coroutine}
            {}

        private:
            Handle m_coroutine;
        };

        Iter begin() {
            if (m_coroutine) {
                m_coroutine.resume();
            }
            return Iter{m_coroutine};
        }
        std::default_sentinel_t end() {
            return {};
        }

    private:
        Handle m_coroutine;
    };

    template<std::integral T>
    Generator<T> range(T first, T last) {
        while (first < last) {
            co_yield first++;
        }
    }

    int main() {
        for (int i : range(-4, 8)) {
            std::cout << i << ' ';
        }
        std::cout << '\n';
    }

输出：

    -4 -3 -2 -1 0 1 2 3 4 5 6 7

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 3460 | C++20 | `coroutine_handle` 的公开基类能将它置于不想要的状态 | 移除继承