std::coroutine_traits
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_type | R::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