// // execution/prefer_only.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2023 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_PREFER_ONLY_HPP #define ASIO_EXECUTION_PREFER_ONLY_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/is_applicable_property.hpp" #include "asio/prefer.hpp" #include "asio/query.hpp" #include "asio/traits/static_query.hpp" #include "asio/detail/push_options.hpp" namespace asio { #if defined(GENERATING_DOCUMENTATION) namespace execution { /// A property adapter that is used with the polymorphic executor wrapper /// to mark properties as preferable, but not requirable. template struct prefer_only { /// The prefer_only adapter applies to the same types as the nested property. template static constexpr bool is_applicable_property_v = is_applicable_property::value; /// The context_t property cannot be required. static constexpr bool is_requirable = false; /// The context_t property can be preferred, it the underlying property can /// be preferred. /** * @c true if @c Property::is_preferable is @c true, otherwise @c false. */ static constexpr bool is_preferable = automatically_determined; /// The type returned by queries against an @c any_executor. typedef typename Property::polymorphic_query_result_type polymorphic_query_result_type; }; } // namespace execution #else // defined(GENERATING_DOCUMENTATION) namespace execution { namespace detail { template struct prefer_only_is_preferable { ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); }; template struct prefer_only_is_preferable::type> { ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); }; template struct prefer_only_polymorphic_query_result_type { }; template struct prefer_only_polymorphic_query_result_type::type> { typedef typename InnerProperty::polymorphic_query_result_type polymorphic_query_result_type; }; template struct prefer_only_property { InnerProperty property; prefer_only_property(const InnerProperty& p) : property(p) { } }; #if defined(ASIO_HAS_DECLTYPE) \ && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) template struct prefer_only_property().value()) >::type> { InnerProperty property; prefer_only_property(const InnerProperty& p) : property(p) { } ASIO_CONSTEXPR auto value() const ASIO_NOEXCEPT_IF(( noexcept(asio::declval().value()))) -> decltype(asio::declval().value()) { return property.value(); } }; #else // defined(ASIO_HAS_DECLTYPE) // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) struct prefer_only_memfns_base { void value(); }; template struct prefer_only_memfns_derived : T, prefer_only_memfns_base { }; template struct prefer_only_memfns_check { }; template char (&prefer_only_value_memfn_helper(...))[2]; template char prefer_only_value_memfn_helper( prefer_only_memfns_check< void (prefer_only_memfns_base::*)(), &prefer_only_memfns_derived::value>*); template struct prefer_only_property(0)) != 1 && !is_same::value >::type> { InnerProperty property; prefer_only_property(const InnerProperty& p) : property(p) { } ASIO_CONSTEXPR typename InnerProperty::polymorphic_query_result_type value() const { return property.value(); } }; #endif // defined(ASIO_HAS_DECLTYPE) // && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) } // namespace detail template struct prefer_only : detail::prefer_only_is_preferable, detail::prefer_only_polymorphic_query_result_type, detail::prefer_only_property { ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); ASIO_CONSTEXPR prefer_only(const InnerProperty& p) : detail::prefer_only_property(p) { } #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template static ASIO_CONSTEXPR typename traits::static_query::result_type static_query() ASIO_NOEXCEPT_IF(( traits::static_query::is_noexcept)) { return traits::static_query::value(); } template ())> static ASIO_CONSTEXPR const T static_query_v = prefer_only::static_query(); #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template friend ASIO_CONSTEXPR typename prefer_result::type prefer(const Executor& ex, const prefer_only& p, typename enable_if< is_same::value >::type* = 0, typename enable_if< can_prefer::value >::type* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. ASIO_NOEXCEPT_IF(( is_nothrow_prefer::value)) #endif // !defined(ASIO_MSVC) // && !defined(__clang__) { return asio::prefer(ex, p.property); } template friend ASIO_CONSTEXPR typename query_result::type query(const Executor& ex, const prefer_only& p, typename enable_if< is_same::value >::type* = 0, typename enable_if< can_query::value >::type* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. ASIO_NOEXCEPT_IF(( is_nothrow_query::value)) #endif // !defined(ASIO_MSVC) // && !defined(__clang__) { return asio::query(ex, p.property); } }; #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template template const T prefer_only::static_query_v; #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) } // namespace execution template struct is_applicable_property > : is_applicable_property { }; namespace traits { #if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \ || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) template struct static_query > : static_query { }; #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) template struct prefer_free_default, typename enable_if< can_prefer::value >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_prefer::value)); typedef typename prefer_result::type result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) #if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) template struct query_free, typename enable_if< can_query::value >::type> { ASIO_STATIC_CONSTEXPR(bool, is_valid = true); ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_query::value)); typedef typename query_result::type result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) } // namespace traits #endif // defined(GENERATING_DOCUMENTATION) } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_EXECUTION_PREFER_ONLY_HPP