命名空间
变体
操作

std::coroutine_handle, std::noop_coroutine_handle

来自 cppreference.com
< cpp‎ | coroutine
 
 
工具库
语言支持
类型支持 (基本类型,RTTI)
库功能测试宏 (C++20)
动态内存管理
程序工具
协程支持 (C++20)
可变参数函数
调试支持
(C++26)
三方比较
(C++20)
(C++20)(C++20)(C++20)
(C++20)(C++20)(C++20)
通用工具
日期和时间
函数对象
格式化库 (C++20)
(C++11)
关系运算符 (C++20 中已弃用)
整数比较函数
(C++20)(C++20)(C++20)   
(C++20)
交换类型操作
(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)
空操作协程
平凡的 awaitables
范围生成器
(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 的每个特化都是 TriviallyCopyable.

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

内容

[编辑] 数据成员

成员名称 定义
ptr (私有) 指向协程状态的指针 void*.
(仅供说明目的的成员对象*)

[编辑] 成员函数

构造 coroutine_handle 对象
(公共成员函数) [编辑]
(C++20)
分配 coroutine_handle 对象
(公共成员函数) [编辑]
转换
获取类型擦除的 coroutine_handle
(公共成员函数) [编辑]
观察者
(C++20)
检查协程是否已完成
(公共成员函数) [编辑]
检查句柄是否代表协程
(公共成员函数) [编辑]
控制
恢复协程的执行
(公共成员函数) [编辑]
(C++20)
销毁协程
(公共成员函数) [编辑]
承诺访问
(C++20)
访问协程的承诺
(公共成员函数) [编辑]
[静态] (C++20)
从协程的承诺对象创建 coroutine_handle
(公共静态成员函数) [编辑]
导出/导入
(C++20)
导出底层地址,即支持协程的指针
(公共成员函数) [编辑]
[静态] (C++20)
从指针导入协程
(公共静态成员函数) [编辑]

[编辑] 非成员函数

比较两个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 {};
        }
        // Disallow co_await in generator coroutines.
        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;
    }
 
    // Range-based for loop support.
    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++ 标准。

DR 应用于 发布的行为 正确行为
LWG 3460 C++20 coroutine_handle 的公共基类可能将其置于不希望的状态 继承已删除

[编辑] 参见

(C++23)
一个view,它表示同步的协程生成器
(类模板) [编辑]