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 の特殊化は TriviallyCopyable です。

プログラムが std::coroutine_handle に対する特殊化を追加する場合、動作は未定義です。

目次

データメンバ

メンバー名 定義
ptr (非公開) コルーチン状態への void * ポインタ。
説明専用メンバーオブジェクト*

メンバー関数

coroutine_handle オブジェクトを構築する
(public member function)
coroutine_handle オブジェクトを代入する
(public member function)
変換
型消去された coroutine_handle を取得する
(public member function)
オブザーバー
コルーチンが完了したかどうかをチェックする
(public member function)
ハンドルがコルーチンを表しているかどうかをチェックする
(public member function)
制御
コルーチンの実行を再開する
(public member function)
コルーチンを破棄する
(public member function)
プロミスアクセス
コルーチンのプロミスにアクセスする
(public member function)
コルーチンのプロミスオブジェクトから coroutine_handle を作成する
(public static member function)
エクスポート/インポート
基盤となるアドレス(コルーチンを支えるポインタ)をエクスポートする
(public member function)
ポインタからコルーチンをインポートする
(public static member function)

非メンバー関数

2つの coroutine_handle オブジェクトを比較する
(関数)

ヘルパークラス

std::coroutine_handle のハッシュサポート
(クラステンプレートの特殊化)

注記

A 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
(注:指定された条件に基づき、HTMLタグ・属性は一切翻訳せず、C++固有用語も翻訳していません。表示テキスト「std::integral」はC++標準ライブラリのコンセプト名であるため、原文のまま保持しています) 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 を表す コルーチン ジェネレータ
(クラステンプレート)