// // execution/execute.hpp // ~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2020 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 BOOST_ASIO_EXECUTION_EXECUTE_HPP #define BOOST_ASIO_EXECUTION_EXECUTE_HPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include #include #include #include #include #include #include #if defined(GENERATING_DOCUMENTATION) namespace boost { 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 } // namespace boost #else // defined(GENERATING_DOCUMENTATION) namespace boost { namespace asio { namespace execution { template struct is_sender_to; namespace detail { template void submit_helper(BOOST_ASIO_MOVE_ARG(S) s, BOOST_ASIO_MOVE_ARG(R) r); } // namespace detail } // namespace execution } // namespace asio } // namespace boost namespace asio_execution_execute_fn { using boost::asio::conditional; using boost::asio::decay; using boost::asio::declval; using boost::asio::enable_if; using boost::asio::execution::detail::as_receiver; using boost::asio::execution::detail::is_as_invocable; using boost::asio::execution::is_sender_to; using boost::asio::false_type; using boost::asio::result_of; using boost::asio::traits::execute_free; using boost::asio::traits::execute_member; using boost::asio::true_type; void execute(); enum overload_type { call_member, call_free, adapter, ill_formed }; template struct call_traits { BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); }; template struct call_traits::is_valid ) >::type> : execute_member { BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; template struct call_traits::is_valid && execute_free::is_valid ) >::type> : execute_free { BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free); }; template struct call_traits::is_valid && !execute_free::is_valid && conditional::type&()>::type >::type::value && conditional< !is_as_invocable< typename decay::type >::value, is_sender_to< T, as_receiver::type, T> >, false_type >::type::value ) >::type> { BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter); BOOST_ASIO_STATIC_CONSTEXPR(bool, is_valid = true); BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false); typedef void result_type; }; struct impl { template BOOST_ASIO_CONSTEXPR typename enable_if< call_traits::overload == call_member, typename call_traits::result_type >::type operator()( BOOST_ASIO_MOVE_ARG(T) t, BOOST_ASIO_MOVE_ARG(F) f) const BOOST_ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return BOOST_ASIO_MOVE_CAST(T)(t).execute(BOOST_ASIO_MOVE_CAST(F)(f)); } template BOOST_ASIO_CONSTEXPR typename enable_if< call_traits::overload == call_free, typename call_traits::result_type >::type operator()( BOOST_ASIO_MOVE_ARG(T) t, BOOST_ASIO_MOVE_ARG(F) f) const BOOST_ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return execute(BOOST_ASIO_MOVE_CAST(T)(t), BOOST_ASIO_MOVE_CAST(F)(f)); } template BOOST_ASIO_CONSTEXPR typename enable_if< call_traits::overload == adapter, typename call_traits::result_type >::type operator()( BOOST_ASIO_MOVE_ARG(T) t, BOOST_ASIO_MOVE_ARG(F) f) const BOOST_ASIO_NOEXCEPT_IF(( call_traits::is_noexcept)) { return boost::asio::execution::detail::submit_helper( BOOST_ASIO_MOVE_CAST(T)(t), as_receiver::type, T>( BOOST_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 boost { namespace asio { namespace execution { namespace { static BOOST_ASIO_CONSTEXPR const asio_execution_execute_fn::impl& execute = asio_execution_execute_fn::static_instance<>::instance; } // namespace template struct can_execute : integral_constant::overload != asio_execution_execute_fn::ill_formed> { }; #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) template constexpr bool can_execute_v = can_execute::value; #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES) } // namespace execution } // namespace asio } // namespace boost #endif // defined(GENERATING_DOCUMENTATION) #include #endif // BOOST_ASIO_EXECUTION_EXECUTE_HPP