std::coroutine_handle

来自cppreference.com
< cpp‎ | coroutine
 
 
工具库
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中弃用)
整数比较函数
(C++20)(C++20)(C++20)
(C++20)
swap 与类型运算
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
常用词汇类型
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)
初等字符串转换
(C++17)
(C++17)
 
协程支持
协程特征
协程柄
coroutine_handle
(C++20)
无操作协程
平凡可等待体
 
 
在标头 <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) ,并保有一个指向协程状态的指针作为其仅有的非静态成员。

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

成员函数

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

非成员函数

比较二个 coroutine_handle 对象
(函数)

辅助类

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++ 标准。

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