Namespaces
Variants

std:: coroutine_handle, std:: noop_coroutine_handle

From cppreference.net
Utilities library
Coroutine support
Coroutine traits
Coroutine handle
coroutine_handle
(C++20)
No-op coroutines
Trivial awaitables
Range generators
(C++23)
定义于头文件 <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 的特化都是 可平凡复制 的。

如果程序为 std::coroutine_handle 添加特化,则行为未定义。

目录

数据成员

成员名称 定义
ptr (private) 指向协程状态的 void * 类型指针。
( 仅用于说明的成员对象* )

成员函数

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

非成员函数

比较两个 coroutine_handle 对象
(函数)

辅助类

std::coroutine_handle 的哈希支持
(类模板特化)

注释

一个 coroutine_handle 可能处于悬空状态,在这种情况下必须谨慎使用该 coroutine_handle ,以避免未定义行为。

示例

#include <coroutine>
#include <iostream>
#include <optional>
template<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;
        [[noreturn]]
        static void unhandled_exception() { throw; }
        std::optional<T> current_value;
    };
    using Handle = std::coroutine_handle<promise_type>;
    explicit Generator(const 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)
        {
            if (m_coroutine)
                m_coroutine.destroy();
            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(const 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, const T last)
{
    while (first < last)
        co_yield first++;
}
int main()
{
    for (const char i : range(65, 91))
        std::cout << i << ' ';
    std::cout << '\n';
}

输出:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

缺陷报告

以下行为变更缺陷报告被追溯应用于先前发布的C++标准。

缺陷报告 适用范围 发布时行为 正确行为
LWG 3460 C++20 coroutine_handle 的公共基类可能导致其处于非预期状态 移除继承关系

参见

(C++23)
表示同步 协程 生成器的 view
(类模板)