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)
Definido en el encabezado <coroutine>
template < class Promise = void >
struct coroutine_handle ;
(1) (desde C++20)
template <>
struct coroutine_handle < void > ;
(2) (desde C++20)
template <>
struct coroutine_handle < std:: noop_coroutine_promise > ;
(3) (desde C++20)
using noop_coroutine_handle =
std :: coroutine_handle < std:: noop_coroutine_promise > ;
(4) (desde C++20)

La plantilla de clase coroutine_handle puede utilizarse para referirse a una corrutina suspendida o en ejecución. Cada especialización de coroutine_handle es un LiteralType .

1) Plantilla principal, puede crearse a partir del objeto promesa de tipo Promise .
2) Especialización std :: coroutine_handle < void > elimina el tipo de promesa. Es convertible desde otras especializaciones.
3) Especialización std :: coroutine_handle < std:: noop_coroutine_promise > se refiere a corrutinas sin operación. No puede crearse a partir de un objeto promise.

En implementaciones típicas, cada especialización de std::coroutine_handle es TriviallyCopyable .

Si el programa añade especializaciones para std::coroutine_handle , el comportamiento no está definido.

Contenidos

Miembros de datos

Nombre del miembro Definición
ptr (privado) Un puntero void * al estado de la corrutina.
( objeto miembro solo para exposición* )

Funciones miembro

construye un objeto coroutine_handle
(función miembro pública)
asigna el objeto coroutine_handle
(función miembro pública)
Conversión
obtiene un coroutine_handle con tipo borrado
(función miembro pública)
Observadores
verifica si la corrutina ha finalizado
(función miembro pública)
verifica si el handle representa una corrutina
(función miembro pública)
Control
reanuda la ejecución de la corrutina
(función miembro pública)
destruye una corrutina
(función miembro pública)
Acceso a Promise
accede al promise de una corrutina
(función miembro pública)
crea un coroutine_handle desde el objeto promise de una corrutina
(función miembro estática pública)
Exportar/Importar
exporta la dirección subyacente, es decir, el puntero que respalda la corrutina
(función miembro pública)
importa una corrutina desde un puntero
(función miembro estática pública)

Funciones no miembro

compara dos objetos coroutine_handle
(función)

Clases auxiliares

soporte de hash para std::coroutine_handle
(especialización de plantilla de clase)

Notas

Un coroutine_handle puede quedar pendiente, en cuyo caso el coroutine_handle debe utilizarse con cuidado para evitar comportamiento indefinido.

Ejemplo

#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 {};
        }
        // Prohibir co_await en corrutinas generadoras.
        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;
    }
    // Soporte para bucle for basado en rangos.
    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';
}

Salida:

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

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 3460 C++20 la clase base pública de coroutine_handle podría dejarlo en un estado no deseado herencia eliminada

Véase también

(C++23)
Una view que representa un generador síncrono de corrutinas
(plantilla de clase)