// // execution/prefer_only.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2024 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 { static constexpr bool is_preferable = false; }; template struct prefer_only_is_preferable > { static constexpr bool is_preferable = true; }; template struct prefer_only_polymorphic_query_result_type { }; template struct prefer_only_polymorphic_query_result_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_WORKING_EXPRESSION_SFINAE) template struct prefer_only_property().value()) > > { InnerProperty property; prefer_only_property(const InnerProperty& p) : property(p) { } constexpr auto value() const noexcept(noexcept(asio::declval().value())) -> decltype(asio::declval().value()) { return property.value(); } }; #else // 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 > > { InnerProperty property; prefer_only_property(const InnerProperty& p) : property(p) { } constexpr typename InnerProperty::polymorphic_query_result_type value() const { return property.value(); } }; #endif // 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 { static constexpr bool is_requirable = false; 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 constexpr typename traits::static_query::result_type static_query() noexcept(traits::static_query::is_noexcept) { return traits::static_query::value(); } template ())> static 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 constexpr prefer_result_t prefer(const Executor& ex, const prefer_only& p, enable_if_t< is_same::value >* = 0, enable_if_t< can_prefer::value >* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. noexcept(is_nothrow_prefer::value) #endif // !defined(ASIO_MSVC) // && !defined(__clang__) { return asio::prefer(ex, p.property); } template friend constexpr query_result_t query(const Executor& ex, const prefer_only& p, enable_if_t< is_same::value >* = 0, enable_if_t< can_query::value >* = 0) #if !defined(ASIO_MSVC) \ && !defined(__clang__) // Clang crashes if noexcept is used here. noexcept(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, enable_if_t< can_prefer::value > > { static constexpr bool is_valid = true; static constexpr bool is_noexcept = is_nothrow_prefer::value; typedef prefer_result_t result_type; }; #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT) #if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT) template struct query_free, enable_if_t< can_query::value > > { static constexpr bool is_valid = true; static constexpr bool is_noexcept = is_nothrow_query::value; typedef query_result_t 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