std::coroutine_handle, std::noop_coroutine_handle
| Определён в заголовке <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.
Promise.std::coroutine_handle<void> стирает тип обещания. Она преобразуется из других специализаций.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) |
|
|
[static]
|
создает
coroutine_handle
из объекта promise корутины
(public static member function) |
Экспорт/Импорт |
|
|
экспортирует базовый адрес, т.е. указатель, поддерживающий корутину
(public member function) |
|
|
[static]
|
импортирует корутину из указателя
(public static member function) |
Функции, не являющиеся членами класса
|
(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 {}; } // Запретить 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
, представляющее синхронный
сопрограммный
генератор
(шаблон класса) |