std::coroutine_traits - cppreference.com

From cppreference.com

template<classR,class...Args>structcoroutine_traits;(since C++20)Determines the promise type from the return type and parameter types of a coroutine. The standard library implementation provides a publicly accessible member type promise_type same as R::promise_type if the qualified-id is valid and denotes a type. Otherwise, it has no such member.

Program-defined specializations

of coroutine_traits must define a publicly accessible nested type promise_type, otherwise the program is ill-formed.

Template parameters

R - return type of the coroutine Args - parameter types of the coroutine, including the

implicit object parameter

if the coroutine is a non-static member function Nested types

Name Definition promise_typeR::promise_type if it is valid, or provided by program-defined specializations Possible implementation

namespacedetail{template<class,class...>structcoroutine_traits_base{};template<classR,class...Args>requiresrequires{typenameR::promise_type;}structcoroutine_traits_base<R,Args...>{usingpromise_type=R::promise_type;};}template<classR,class...Args>structcoroutine_traits:detail::coroutine_traits_base<R,Args...>{};Notes

If the coroutine is a non-static member function, then the first type in Args... is the type of the implicit object parameter, and the rest are parameter types of the function (if any).

If std::coroutine_traits<R, Args...>::promise_type does not exist or is not a class type, the corresponding coroutine definition is ill-formed.

Users may define explicit or partial specializations of coroutine_traits dependent on program-defined types to avoid modification to return types.

Example

Run this code

#include<chrono>#include<coroutine>#include<exception>#include<future>#include<iostream>#include<thread>#include<type_traits>// A program-defined type on which the coroutine_traits specializations below dependstructas_coroutine{};// Enable the use of std::future<T> as a coroutine type// by using a std::promise<T> as the promise type.template<typenameT,typename...Args>requires(!std::is_void_v<T>&&!std::is_reference_v<T>)structstd::coroutine_traits<std::future<T>,as_coroutine,Args...>{structpromise_type:std::promise<T>{std::future<T>get_return_object()noexcept{returnthis->get_future();}std::suspend_neverinitial_suspend()constnoexcept{return{};}std::suspend_neverfinal_suspend()constnoexcept{return{};}voidreturn_value(constT&value)noexcept(std::is_nothrow_copy_constructible_v<T>){this->set_value(value);}voidreturn_value(T&&value)noexcept(std::is_nothrow_move_constructible_v<T>){this->set_value(std::move(value));}voidunhandled_exception()noexcept{this->set_exception(std::current_exception());}};};// Same for std::future<void>.template<typename...Args>structstd::coroutine_traits<std::future<void>,as_coroutine,Args...>{structpromise_type:std::promise<void>{std::future<void>get_return_object()noexcept{returnthis->get_future();}std::suspend_neverinitial_suspend()constnoexcept{return{};}std::suspend_neverfinal_suspend()constnoexcept{return{};}voidreturn_void()noexcept{this->set_value();}voidunhandled_exception()noexcept{this->set_exception(std::current_exception());}};};// Allow co_await'ing std::future<T> and std::future<void>// by naively spawning a new thread for each co_await.template<typenameT>autooperatorco_await(std::future<T>future)noexceptrequires(!std::is_reference_v<T>){structawaiter:std::future<T>{boolawait_ready()constnoexcept{usingnamespacestd::chrono_literals;returnthis->wait_for(0s)!=std::future_status::timeout;}voidawait_suspend(std::coroutine_handle<>cont)const{std::thread([this,cont]{this->wait();cont();}).detach();}Tawait_resume(){returnthis->get();}};returnawaiter{std::move(future)};}// Utilize the infrastructure we have established.std::future<int>compute(as_coroutine){inta=co_awaitstd::async([]{return6;});intb=co_awaitstd::async([]{return7;});co_returna*b;}std::future<void>fail(as_coroutine){throwstd::runtime_error("bleah");co_return;}intmain(){std::cout<<compute({}).get()<<'\n';try{fail({}).get();}catch(conststd::runtime_error&e){std::cout<<"error: "<<e.what()<<'\n';}}Output:

42 error: bleah