Namespaces
Variants

std::coroutine_handle, std::noop_coroutine_handle

С ru.cppreference.net
 
 
Библиотека утилит
Поддержка языка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования возможностей библиотеки (C++20)
Программные утилиты
Функции с переменным числом аргументов
Поддержка корутин (C++20)
Поддержка контрактов (C++26)
Трёхстороннее сравнение
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Общие утилиты
Реляционные операторы (устарело в C++20)
 
Поддержка корутин
Трейты корутин
Дескриптор корутины
No-op корутины
Тривиальные ожидаемые
Генераторы диапазонов
(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> ссылается на no-op корутины. Она не может быть создана из объекта обещания.

В типичных реализациях каждая специализация std::coroutine_handle является TriviallyCopyable.

Если программа добавляет специализации для std::coroutine_handle, поведение не определено.

Члены данных

Название члена Определение
ptr (private) Указатель 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)
Доступ к Promise
получает доступ к promise корутины
(public member function)
создает coroutine_handle из объекта promise корутины
(public static member function)
Экспорт/Импорт
экспортирует базовый адрес, т.е. указатель, поддерживающий корутину
(public member function)
импортирует корутину из указателя
(public static member function)

Функции, не являющиеся членами класса

сравнивает два объекта 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++.

DR Applied to Behavior as published Correct behavior
LWG 3460 C++20 публичный базовый класс coroutine_handle мог оставить его в нежелательном состоянии наследование удалено

Смотрите также

(C++23)
Представление view , представляющее синхронный сопрограммный генератор
(шаблон класса)