Espacios de nombres
Variantes
Acciones

std::coroutine_traits

De cppreference.com
< cpp‎ | coroutine
 
 
Biblioteca de servicios
 
Apoyo de corrutinas
Rasgos de corrutinas
coroutine_traits
(C++20)
Identificador de corrutina
Corrutinas no operativas
En espera triviales
 
Definido en el archivo de encabezado <coroutine>
template<class R, class... Args>
struct coroutine_traits;
(desde C++20)

Determina el tipo de promesa a partir del tipo de retorno y los tipos de los parámetros de una corrutina. La biblioteca estándar proporciona un tipo miembro públicamente accesible promise_type igual que R::promise_type si el id-calificado es válido y denota un tipo; de lo contrario, no tiene tal miembro.

Las especializaciones definidas por el programa de coroutine_traits deberán definir un tipo miembro públicamente accesible promise_type; de lo contrario, el comportamiento no está definido.

Contenido

[editar]Parámetros de plantilla

R - Tipo de retorno de la corrutina.
Args - Los tipos de los parámetros de la corrutina, incluyendo el parámetro objeto implícito parámetro objeto implícito si la corrutina es una función miembro no estática.

[editar]Tipos miembro

Tipo Definición
promise_typeR::promise_type si es válido, o proporcionado por las especializaciones definidas por el programa.

[editar]Posible implementación

template<class, class...>struct coroutine_traits {};   template<class R, class... Args> requires requires {typename R::promise_type}struct coroutine_traits<R, Args...>{using promise_type = R::promise_type;};

[editar]Notas

Si la corrutina es una función miembro no estática, entonces el primer tipo en Args... es el tipo del parámetro objeto implícito, y el resto son los tipos de los parámetros de la función (si los hay).

Si std::coroutine_traits<R, Args...>::promise_type no existe o no es un tipo clase, la definición correspondiente de la corrutina está mal formada.

Los usuarios pueden definir especializaciones parciales o explícitas (totales) de coroutine_traits dependientes de los tipos definidos por el programa para evitar la modificación a los tipos de retorno.

[editar]Ejemplo

#include <chrono>#include <coroutine>#include <exception>#include <future>#include <iostream>#include <thread>#include <type_traits>   // Habilitar el uso de std::future<T> como un tipo corrutina// usando a std::promise<T> como el tipo promesa.template<typename T, typename... Args> requires(!std::is_void_v<T>&&!std::is_reference_v<T>)struct std::coroutine_traits<std::future<T>, Args...>{struct promise_type :std::promise<T>{std::future<T> get_return_object()noexcept{return this->get_future();}   std::suspend_never initial_suspend()constnoexcept{return{};}std::suspend_never final_suspend()constnoexcept{return{};}   void return_value(const T &value)noexcept(std::is_nothrow_copy_constructible_v<T>){ this->set_value(value);}void return_value(T &&value)noexcept(std::is_nothrow_move_constructible_v<T>){ this->set_value(std::move(value));}void unhandled_exception()noexcept{ this->set_exception(std::current_exception());}};};   // Lo mismo para std::future<void>.template<typename... Args>struct std::coroutine_traits<std::future<void>, Args...>{struct promise_type :std::promise<void>{std::future<void> get_return_object()noexcept{return this->get_future();}   std::suspend_never initial_suspend()constnoexcept{return{};}std::suspend_never final_suspend()constnoexcept{return{};}   void return_void()noexcept{ this->set_value();}void unhandled_exception()noexcept{ this->set_exception(std::current_exception());}};};   // Permitir la espera con co_await para std::future<T> y std::future<void>// ingenuamente iniciando un nuevo hilo para cada co_await.template<typename T>auto operator co_await(std::future<T> future)noexcept requires(!std::is_reference_v<T>){struct awaiter :std::future<T>{bool await_ready()constnoexcept{usingnamespace std::chrono_literals;return this->wait_for(0s)!=std::future_status::timeout;}void await_suspend(std::coroutine_handle<> cont)const{std::thread([this, cont]{ this->wait(); cont();}).detach();} T await_resume(){return this->get();}};return awaiter{std::move(future)};}   // Utilizar la infraestructura que hemos establecido.std::future<int> compute(){int a = co_await std::async([]{return6;});int b = co_await std::async([]{return7;}); co_return a * b;}   std::future<void> fail(){throwstd::runtime_error("fuchi"); co_return;}   int main(){std::cout<< compute().get()<<'\n';   try{ fail().get();}catch(conststd::runtime_error&e){std::cout<<"error: "<< e.what()<<'\n';}}

Salida:

42 error: fuchi
close