Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
std::coroutine_traits(3)      C++ Standard Libary     std::coroutine_traits(3)

NAME
       std::coroutine_traits - std::coroutine_traits

Synopsis
	  Defined in header <coroutine>
	  template< class R, class... Args >  (since C++20)
	  struct coroutine_traits;

	  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	shall define a
       publicly
	  accessible member type promise_type; otherwise, the behavior is  un-
       defined.

Template parameters
	  R    - return	type of	the coroutine
	  Args	- parameter types of the coroutine, including the implicit ob-
       ject parameter if
		 the coroutine is a non-static member function

Member types
	  Type	       Definition
	  promise_type R::promise_type if it is	valid, or provided by program-
       defined
		       specializations

Possible implementation
	  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 = typename R::promise_type;
	  };

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 parame-
       ter 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	corou-
       tine_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 specializa-
       tions below depend
	struct as_coroutine {};

	// Enable the use of std::future<T> as a coroutine type
	// by using a std::promise<T> as the promise type.
	template <typename T, typename... Args>
	requires(!std::is_void_v<T> && !std::is_reference_v<T>)
	struct std::coroutine_traits<std::future<T>, as_coroutine, Args...> {
	  struct promise_type :	std::promise<T>	{
	    std::future<T> get_return_object() noexcept	{
	      return this->get_future();
	    }

	    std::suspend_never initial_suspend() const noexcept	{ return {}; }
	    std::suspend_never final_suspend() const noexcept {	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());
	    }
	  };
	};

	// Same	for std::future<void>.
	template <typename... Args>
	struct std::coroutine_traits<std::future<void>,	as_coroutine, Args...>
       {
	  struct promise_type :	std::promise<void> {
	    std::future<void> get_return_object() noexcept {
	      return this->get_future();
	    }

	    std::suspend_never initial_suspend() const noexcept	{ return {}; }
	    std::suspend_never final_suspend() const noexcept {	return {}; }

	    void return_void() noexcept	{
	      this->set_value();
	    }
	    void unhandled_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 <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() const noexcept {
	      using namespace 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)};
	}

	// Utilize the infrastructure we have established.
	std::future<int> compute(as_coroutine) {
	  int a	= co_await std::async([] { return 6; });
	  int b	= co_await std::async([] { return 7; });
	  co_return a *	b;
	}

	std::future<void> fail(as_coroutine) {
	  throw	std::runtime_error("bleah");
	  co_return;
	}

	int main() {
	  std::cout << compute({}).get() << '\n';

	  try {
	    fail({}).get();
	  } catch (const std::runtime_error &e)	{
	    std::cout << "error: " << e.what() << '\n';
	  }
	}

Output:
	42
	error: bleah

http://cppreference.com		  2022.07.31	      std::coroutine_traits(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=std::coroutine_traits&sektion=3&manpath=FreeBSD+Ports+15.0>

home | help