332 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
		
		
			
		
	
	
			332 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			C++
		
	
	
	
|  | //
 | ||
|  | // 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 <typename Property> | ||
|  | struct prefer_only | ||
|  | { | ||
|  |   /// The prefer_only adapter applies to the same types as the nested property.
 | ||
|  |   template <typename T> | ||
|  |   static constexpr bool is_applicable_property_v = | ||
|  |     is_applicable_property<T, 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 <typename InnerProperty, typename = void> | ||
|  | struct prefer_only_is_preferable | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_preferable = false); | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename InnerProperty> | ||
|  | struct prefer_only_is_preferable<InnerProperty, | ||
|  |     typename enable_if< | ||
|  |       InnerProperty::is_preferable | ||
|  |     >::type> | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename InnerProperty, typename = void> | ||
|  | struct prefer_only_polymorphic_query_result_type | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename InnerProperty> | ||
|  | struct prefer_only_polymorphic_query_result_type<InnerProperty, | ||
|  |     typename void_type< | ||
|  |       typename InnerProperty::polymorphic_query_result_type | ||
|  |     >::type> | ||
|  | { | ||
|  |   typedef typename InnerProperty::polymorphic_query_result_type | ||
|  |     polymorphic_query_result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename InnerProperty, typename = void> | ||
|  | 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 <typename InnerProperty> | ||
|  | struct prefer_only_property<InnerProperty, | ||
|  |     typename void_type< | ||
|  |       decltype(asio::declval<const InnerProperty>().value()) | ||
|  |     >::type> | ||
|  | { | ||
|  |   InnerProperty property; | ||
|  | 
 | ||
|  |   prefer_only_property(const InnerProperty& p) | ||
|  |     : property(p) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  |   ASIO_CONSTEXPR auto value() const | ||
|  |     ASIO_NOEXCEPT_IF(( | ||
|  |       noexcept(asio::declval<const InnerProperty>().value()))) | ||
|  |     -> decltype(asio::declval<const InnerProperty>().value()) | ||
|  |   { | ||
|  |     return property.value(); | ||
|  |   } | ||
|  | }; | ||
|  | 
 | ||
|  | #else // defined(ASIO_HAS_DECLTYPE)
 | ||
|  |       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)
 | ||
|  | 
 | ||
|  | struct prefer_only_memfns_base | ||
|  | { | ||
|  |   void value(); | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename T> | ||
|  | struct prefer_only_memfns_derived | ||
|  |   : T, prefer_only_memfns_base | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename T, T> | ||
|  | struct prefer_only_memfns_check | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | template <typename> | ||
|  | char (&prefer_only_value_memfn_helper(...))[2]; | ||
|  | 
 | ||
|  | template <typename T> | ||
|  | char prefer_only_value_memfn_helper( | ||
|  |     prefer_only_memfns_check< | ||
|  |       void (prefer_only_memfns_base::*)(), | ||
|  |       &prefer_only_memfns_derived<T>::value>*); | ||
|  | 
 | ||
|  | template <typename InnerProperty> | ||
|  | struct prefer_only_property<InnerProperty, | ||
|  |     typename enable_if< | ||
|  |       sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1 | ||
|  |         && !is_same<typename InnerProperty::polymorphic_query_result_type, | ||
|  |           void>::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 <typename InnerProperty> | ||
|  | struct prefer_only : | ||
|  |   detail::prefer_only_is_preferable<InnerProperty>, | ||
|  |   detail::prefer_only_polymorphic_query_result_type<InnerProperty>, | ||
|  |   detail::prefer_only_property<InnerProperty> | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_requirable = false); | ||
|  | 
 | ||
|  |   ASIO_CONSTEXPR prefer_only(const InnerProperty& p) | ||
|  |     : detail::prefer_only_property<InnerProperty>(p) | ||
|  |   { | ||
|  |   } | ||
|  | 
 | ||
|  | #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
 | ||
|  |   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) | ||
|  |   template <typename T> | ||
|  |   static ASIO_CONSTEXPR | ||
|  |   typename traits::static_query<T, InnerProperty>::result_type | ||
|  |   static_query() | ||
|  |     ASIO_NOEXCEPT_IF(( | ||
|  |       traits::static_query<T, InnerProperty>::is_noexcept)) | ||
|  |   { | ||
|  |     return traits::static_query<T, InnerProperty>::value(); | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename E, typename T = decltype(prefer_only::static_query<E>())> | ||
|  |   static ASIO_CONSTEXPR const T static_query_v | ||
|  |     = prefer_only::static_query<E>(); | ||
|  | #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
 | ||
|  |        //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
 | ||
|  | 
 | ||
|  |   template <typename Executor, typename Property> | ||
|  |   friend ASIO_CONSTEXPR | ||
|  |   typename prefer_result<const Executor&, const InnerProperty&>::type | ||
|  |   prefer(const Executor& ex, const prefer_only<Property>& p, | ||
|  |       typename enable_if< | ||
|  |         is_same<Property, InnerProperty>::value | ||
|  |       >::type* = 0, | ||
|  |       typename enable_if< | ||
|  |         can_prefer<const Executor&, const InnerProperty&>::value | ||
|  |       >::type* = 0) | ||
|  | #if !defined(ASIO_MSVC) \
 | ||
|  |   && !defined(__clang__) // Clang crashes if noexcept is used here.
 | ||
|  |     ASIO_NOEXCEPT_IF(( | ||
|  |       is_nothrow_prefer<const Executor&, const InnerProperty&>::value)) | ||
|  | #endif // !defined(ASIO_MSVC)
 | ||
|  |        //   && !defined(__clang__)
 | ||
|  |   { | ||
|  |     return asio::prefer(ex, p.property); | ||
|  |   } | ||
|  | 
 | ||
|  |   template <typename Executor, typename Property> | ||
|  |   friend ASIO_CONSTEXPR | ||
|  |   typename query_result<const Executor&, const InnerProperty&>::type | ||
|  |   query(const Executor& ex, const prefer_only<Property>& p, | ||
|  |       typename enable_if< | ||
|  |         is_same<Property, InnerProperty>::value | ||
|  |       >::type* = 0, | ||
|  |       typename enable_if< | ||
|  |         can_query<const Executor&, const InnerProperty&>::value | ||
|  |       >::type* = 0) | ||
|  | #if !defined(ASIO_MSVC) \
 | ||
|  |   && !defined(__clang__) // Clang crashes if noexcept is used here.
 | ||
|  |     ASIO_NOEXCEPT_IF(( | ||
|  |       is_nothrow_query<const Executor&, const InnerProperty&>::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 <typename InnerProperty> template <typename E, typename T> | ||
|  | const T prefer_only<InnerProperty>::static_query_v; | ||
|  | #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
 | ||
|  |        //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
 | ||
|  | 
 | ||
|  | } // namespace execution
 | ||
|  | 
 | ||
|  | template <typename T, typename InnerProperty> | ||
|  | struct is_applicable_property<T, execution::prefer_only<InnerProperty> > | ||
|  |   : is_applicable_property<T, InnerProperty> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | namespace traits { | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
 | ||
|  |   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES) | ||
|  | 
 | ||
|  | template <typename T, typename InnerProperty> | ||
|  | struct static_query<T, execution::prefer_only<InnerProperty> > : | ||
|  |   static_query<T, const InnerProperty&> | ||
|  | { | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
 | ||
|  |        //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename InnerProperty> | ||
|  | struct prefer_free_default<T, execution::prefer_only<InnerProperty>, | ||
|  |     typename enable_if< | ||
|  |       can_prefer<const T&, const InnerProperty&>::value | ||
|  |     >::type> | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = | ||
|  |     (is_nothrow_prefer<const T&, const InnerProperty&>::value)); | ||
|  | 
 | ||
|  |   typedef typename prefer_result<const T&, | ||
|  |       const InnerProperty&>::type result_type; | ||
|  | }; | ||
|  | 
 | ||
|  | #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
 | ||
|  | 
 | ||
|  | #if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
 | ||
|  | 
 | ||
|  | template <typename T, typename InnerProperty> | ||
|  | struct query_free<T, execution::prefer_only<InnerProperty>, | ||
|  |     typename enable_if< | ||
|  |       can_query<const T&, const InnerProperty&>::value | ||
|  |     >::type> | ||
|  | { | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_valid = true); | ||
|  |   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = | ||
|  |     (is_nothrow_query<const T&, const InnerProperty&>::value)); | ||
|  | 
 | ||
|  |   typedef typename query_result<const T&, | ||
|  |       const InnerProperty&>::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
 |