Пространства имён
Варианты
Действия

std::coroutine_handle, std::noop_coroutine_handle

Материал из cppreference.com
< cpp‎ | coroutine
 
 
Библиотека утилит
Языковая поддержка
Поддержка типов (базовые типы, RTTI)
Макросы тестирования функциональности библиотеки (C++20)    
Управление динамической памятью
Программные утилиты
Поддержка сопрограмм (C++20)
Вариативные функции
Трёхстороннее сравнение (C++20)
(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)
��опрограммы без операций
Тривиальные ожидания
Генераторы диапазонов
(C++23)
 
std::coroutine_handle
Функции-лементы
Преобразование
Наблюдатели
Контроль
Доступ к обещанию
Экспорт/импорт
Функции, не являющиеся элементами
(C++20)(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 не определено.

Содержание

[править] Элементы данных

Имя элемента Определение
ptr (private) Указатель void* на состояние сопрограммы.
(только для пояснения объект элемент*)

[править] Функции-элементы

создаёт объект coroutine_handle
(public функция-элемент) [править]
(C++20)
присваивает объект coroutine_handle
(public функция-элемент) [править]
Преобразование
получает стёртый тип coroutine_handle
(public функция-элемент) [править]
Наблюдатели
(C++20)
проверяет, завершилась ли сопрограмма
(public функция-элемент) [править]
проверяет, представляет ли дескриптор сопрограмму
(public функция-элемент) [править]
Контроль
возобновляет выполнение сопрограммы
(public функция-элемент) [править]
(C++20)
уничтожает сопрограмму
(public функция-элемент) [править]
Доступ к обещанию
(C++20)
предоставляет доступ к обещанию сопрограммы
(public функция-элемент) [править]
[static] (C++20)
создаёт coroutine_handle из объекта обещания сопрограммы
(public static функция-элемент) [править]
Экспорт/Импорт
(C++20)
экспортирует базовый адрес, то есть указатель, поддерживающий сопрограмму
(public функция-элемент) [править]
[static] (C++20)
импортирует сопрограмму из указателя
(public static функция-элемент) [править]

[править] Функции, не являющиеся элементами

сравнивает два объекта 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;
    }
 
    // На основе диапазона для поддержки циклов.
    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, представляющий синхронный генератор сопрограмм
(шаблон класса) [править]