// // experimental/detail/coro_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2021-2023 Klemens D. Morgenstern // (klemens dot morgenstern at gmx dot net) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP #define ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include #include #include "asio/any_io_executor.hpp" namespace asio { namespace experimental { namespace detail { template concept convertible_to = std::is_convertible_v; template concept decays_to_executor = execution::executor>; template concept execution_context = requires (T& t) { {t.get_executor()} -> convertible_to; }; template struct coro_result { using type = std::variant; }; template struct coro_result { using type = std::optional; }; template struct coro_result { using type = Return; }; template struct coro_result { using type = YieldReturn; }; template <> struct coro_result { using type = void; }; template using coro_result_t = typename coro_result::type; template struct coro_handler; template <> struct coro_handler { using type = void(std::exception_ptr); }; template <> struct coro_handler { using type = void(); }; template struct coro_handler { using type = void(std::exception_ptr, T); }; template struct coro_handler { using type = void(T); }; template using coro_handler_t = typename coro_handler::type; } // namespace detail #if defined(GENERATING_DOCUMENTATION) /// The traits describing the resumable coroutine behaviour. /** * Template parameter @c Yield specifies type or signature used by co_yield, * @c Return specifies the type used for co_return, and @c Executor specifies * the underlying executor type. */ template struct coro_traits { /// The value that can be passed into a symmetrical cororoutine. @c void if /// asymmetrical. using input_type = argument_dependent; /// The type that can be passed out through a co_yield. using yield_type = argument_dependent; /// The type that can be passed out through a co_return. using return_type = argument_dependent; /// The type received by a co_await or async_resume. It's a combination of /// yield and return. using result_type = argument_dependent; /// The signature used by the async_resume. using signature_type = argument_dependent; /// Whether or not the coroutine is noexcept. constexpr static bool is_noexcept = argument_dependent; /// The error type of the coroutine. @c void for noexcept. using error_type = argument_dependent; /// Completion handler type used by async_resume. using completion_handler = argument_dependent; }; #else // defined(GENERATING_DOCUMENTATION) template struct coro_traits { using input_type = void; using yield_type = Yield; using return_type = Return; using result_type = detail::coro_result_t; using signature_type = result_type(); constexpr static bool is_noexcept = false; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; template struct coro_traits { using input_type = void; using yield_type = T; using return_type = Return; using result_type = detail::coro_result_t; using signature_type = result_type(); constexpr static bool is_noexcept = false; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; template struct coro_traits { using input_type = void; using yield_type = T; using return_type = Return; using result_type = detail::coro_result_t; using signature_type = result_type(); constexpr static bool is_noexcept = true; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; template struct coro_traits { using input_type = U; using yield_type = T; using return_type = Return; using result_type = detail::coro_result_t; using signature_type = result_type(input_type); constexpr static bool is_noexcept = false; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; template struct coro_traits { using input_type = U; using yield_type = T; using return_type = Return; using result_type = detail::coro_result_t; using signature_type = result_type(input_type); constexpr static bool is_noexcept = true; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; template struct coro_traits { using input_type = void; using yield_type = void; using return_type = void; using result_type = detail::coro_result_t; using signature_type = result_type(input_type); constexpr static bool is_noexcept = true; using error_type = std::conditional_t; using completion_handler = detail::coro_handler_t; }; #endif // defined(GENERATING_DOCUMENTATION) } // namespace experimental } // namespace asio #endif // ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP