// // execution/execute.hpp // ~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2021 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // 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_EXECUTION_EXECUTE_HPP #define ASIO_EXECUTION_EXECUTE_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/detail/config.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/as_receiver.hpp" #include "asio/traits/execute_member.hpp" #include "asio/traits/execute_free.hpp" #include "asio/detail/push_options.hpp" #if defined(GENERATING_DOCUMENTATION) namespace asio { namespace execution { /// A customisation point that executes a function on an executor. /** * The name execution::execute denotes a customisation point object. * * For some subexpressions e and f, let E be a type * such that decltype((e)) is E and let F be a type * such that decltype((f)) is F. The expression * execution::execute(e, f) is ill-formed if F does not model * invocable, or if E does not model either executor * or sender. Otherwise, it is expression-equivalent to: * * @li e.execute(f), if that expression is valid. If the function * selected does not execute the function object f on the executor * e, the program is ill-formed with no diagnostic required. * * @li Otherwise, execute(e, f), if that expression is valid, with * overload resolution performed in a context that includes the declaration * void execute(); and that does not include a declaration of * execution::execute. If the function selected by overload * resolution does not execute the function object f on the executor * e, the program is ill-formed with no diagnostic required. */ inline constexpr unspecified execute = unspecified; /// A type trait that determines whether a @c execute expression is well-formed. /** * Class template @c can_execute is a trait that is derived from * @c true_type if the expression execution::execute(std::declval(), * std::declval()) is well formed; otherwise @c false_type. */ template struct can_execute : integral_constant { }; } // namespace execution } // namespace asio #else // defined(GENERATING_DOCUMENTATION) namespace asio { namespace execution { template struct is_sender_to; namespace detail { template void submit_helper(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r); } // namespace detail } // namespace execution } // namespace asio namespace asio_execution_execute_fn { using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if; using asio::execution::detail::as_receiver; using asio::execution::detail::is_as_invocable; using asio::execution::is_sender_to; using asio::false_type; using asio::result_of; using asio::traits::execute_free; using asio::traits::execute_member; using asio::true_type; using asio::void_type; void execute(); enum overload_type { call_member, call_free, adapter, ill_formed }; template struct call_traits { ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); }; template struct call_traits::type, F>::is_valid >::type> : execute_member::type, F> { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; template struct call_traits, F>::is_valid >::type, typename enable_if< execute_free::is_valid >::type> : execute_free { ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); }; template struct call_traits::type, F>::is_valid >::type, typename enable_if< !execute_free::is_valid >::type, typename void_type< typename result_of::type&()>::type >::type, typename enable_if< !is_as_invocable::type>::value >::type, typename enable_if< is_sender_to::type, T> >::value >::type> { ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); typedef void result_type; }; struct impl { template struct proxy { #if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) struct type { template auto execute(ASIO_MOVE_ARG(F) f) noexcept( noexcept( declval::type>().execute( ASIO_MOVE_CAST(F)(f)) ) ) -> decltype( declval::type>().execute( ASIO_MOVE_CAST(F)(f)) ); }; #else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) typedef T type; #endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) }; template ASIO_CONSTEXPR typename enable_if< call_traits::overload == call_member, typename call_traits::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return ASIO_MOVE_CAST(T)(t).execute(ASIO_MOVE_CAST(F)(f)); } template ASIO_CONSTEXPR typename enable_if< call_traits::overload == call_free, typename call_traits::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return execute(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(F)(f)); } template ASIO_CONSTEXPR typename enable_if< call_traits::overload == adapter, typename call_traits::result_type >::type operator()( ASIO_MOVE_ARG(T) t, ASIO_MOVE_ARG(F) f) const ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return asio::execution::detail::submit_helper( ASIO_MOVE_CAST(T)(t), as_receiver::type, T>( ASIO_MOVE_CAST(F)(f), 0)); } }; template struct static_instance { static const T instance; }; template const T static_instance::instance = {}; } // namespace asio_execution_execute_fn namespace asio { namespace execution { namespace { static ASIO_CONSTEXPR const asio_execution_execute_fn::impl& execute = asio_execution_execute_fn::static_instance<>::instance; } // namespace typedef asio_execution_execute_fn::impl execute_t; template struct can_execute : integral_constant::overload != asio_execution_execute_fn::ill_formed> { }; #if defined(ASIO_HAS_VARIABLE_TEMPLATES) template constexpr bool can_execute_v = can_execute::value; #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES) } // namespace execution } // namespace asio #endif // defined(GENERATING_DOCUMENTATION) #include "asio/detail/pop_options.hpp" #endif // ASIO_EXECUTION_EXECUTE_HPP