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 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 ob-
       ject parameter if
		 the coroutine is a non-static member function

	  Nested types

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

Possible implementation
	  namespace detail {
	  template<class, class...>
	  struct coroutine_traits_base {};

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

	  template<class R, class... Args>
	  struct coroutine_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  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)		 noex-
       cept(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		  2024.06.10	      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.1.quarterly>

home | help