prefer_only.hpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. //
  2. // execution/prefer_only.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
  6. //
  7. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. #ifndef BOOST_ASIO_EXECUTION_PREFER_ONLY_HPP
  11. #define BOOST_ASIO_EXECUTION_PREFER_ONLY_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/type_traits.hpp>
  17. #include <boost/asio/is_applicable_property.hpp>
  18. #include <boost/asio/prefer.hpp>
  19. #include <boost/asio/query.hpp>
  20. #include <boost/asio/traits/static_query.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. #if defined(GENERATING_DOCUMENTATION)
  25. namespace execution {
  26. /// A property adapter that is used with the polymorphic executor wrapper
  27. /// to mark properties as preferable, but not requirable.
  28. template <typename Property>
  29. struct prefer_only
  30. {
  31. /// The prefer_only adapter applies to the same types as the nested property.
  32. template <typename T>
  33. static constexpr bool is_applicable_property_v =
  34. is_applicable_property<T, Property>::value;
  35. /// The context_t property cannot be required.
  36. static constexpr bool is_requirable = false;
  37. /// The context_t property can be preferred, it the underlying property can
  38. /// be preferred.
  39. /**
  40. * @c true if @c Property::is_preferable is @c true, otherwise @c false.
  41. */
  42. static constexpr bool is_preferable = automatically_determined;
  43. /// The type returned by queries against an @c any_executor.
  44. typedef typename Property::polymorphic_query_result_type
  45. polymorphic_query_result_type;
  46. };
  47. } // namespace execution
  48. #else // defined(GENERATING_DOCUMENTATION)
  49. namespace execution {
  50. namespace detail {
  51. template <typename InnerProperty, typename = void>
  52. struct prefer_only_is_preferable
  53. {
  54. static constexpr bool is_preferable = false;
  55. };
  56. template <typename InnerProperty>
  57. struct prefer_only_is_preferable<InnerProperty,
  58. enable_if_t<
  59. InnerProperty::is_preferable
  60. >
  61. >
  62. {
  63. static constexpr bool is_preferable = true;
  64. };
  65. template <typename InnerProperty, typename = void>
  66. struct prefer_only_polymorphic_query_result_type
  67. {
  68. };
  69. template <typename InnerProperty>
  70. struct prefer_only_polymorphic_query_result_type<InnerProperty,
  71. void_t<
  72. typename InnerProperty::polymorphic_query_result_type
  73. >
  74. >
  75. {
  76. typedef typename InnerProperty::polymorphic_query_result_type
  77. polymorphic_query_result_type;
  78. };
  79. template <typename InnerProperty, typename = void>
  80. struct prefer_only_property
  81. {
  82. InnerProperty property;
  83. prefer_only_property(const InnerProperty& p)
  84. : property(p)
  85. {
  86. }
  87. };
  88. #if defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
  89. template <typename InnerProperty>
  90. struct prefer_only_property<InnerProperty,
  91. void_t<
  92. decltype(boost::asio::declval<const InnerProperty>().value())
  93. >
  94. >
  95. {
  96. InnerProperty property;
  97. prefer_only_property(const InnerProperty& p)
  98. : property(p)
  99. {
  100. }
  101. constexpr auto value() const
  102. noexcept(noexcept(boost::asio::declval<const InnerProperty>().value()))
  103. -> decltype(boost::asio::declval<const InnerProperty>().value())
  104. {
  105. return property.value();
  106. }
  107. };
  108. #else // defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
  109. struct prefer_only_memfns_base
  110. {
  111. void value();
  112. };
  113. template <typename T>
  114. struct prefer_only_memfns_derived
  115. : T, prefer_only_memfns_base
  116. {
  117. };
  118. template <typename T, T>
  119. struct prefer_only_memfns_check
  120. {
  121. };
  122. template <typename>
  123. char (&prefer_only_value_memfn_helper(...))[2];
  124. template <typename T>
  125. char prefer_only_value_memfn_helper(
  126. prefer_only_memfns_check<
  127. void (prefer_only_memfns_base::*)(),
  128. &prefer_only_memfns_derived<T>::value>*);
  129. template <typename InnerProperty>
  130. struct prefer_only_property<InnerProperty,
  131. enable_if_t<
  132. sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1
  133. && !is_same<typename InnerProperty::polymorphic_query_result_type,
  134. void>::value
  135. >
  136. >
  137. {
  138. InnerProperty property;
  139. prefer_only_property(const InnerProperty& p)
  140. : property(p)
  141. {
  142. }
  143. constexpr typename InnerProperty::polymorphic_query_result_type
  144. value() const
  145. {
  146. return property.value();
  147. }
  148. };
  149. #endif // defined(BOOST_ASIO_HAS_WORKING_EXPRESSION_SFINAE)
  150. } // namespace detail
  151. template <typename InnerProperty>
  152. struct prefer_only :
  153. detail::prefer_only_is_preferable<InnerProperty>,
  154. detail::prefer_only_polymorphic_query_result_type<InnerProperty>,
  155. detail::prefer_only_property<InnerProperty>
  156. {
  157. static constexpr bool is_requirable = false;
  158. constexpr prefer_only(const InnerProperty& p)
  159. : detail::prefer_only_property<InnerProperty>(p)
  160. {
  161. }
  162. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  163. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  164. template <typename T>
  165. static constexpr
  166. typename traits::static_query<T, InnerProperty>::result_type
  167. static_query()
  168. noexcept(traits::static_query<T, InnerProperty>::is_noexcept)
  169. {
  170. return traits::static_query<T, InnerProperty>::value();
  171. }
  172. template <typename E, typename T = decltype(prefer_only::static_query<E>())>
  173. static constexpr const T static_query_v
  174. = prefer_only::static_query<E>();
  175. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  176. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  177. template <typename Executor, typename Property>
  178. friend constexpr
  179. prefer_result_t<const Executor&, const InnerProperty&>
  180. prefer(const Executor& ex, const prefer_only<Property>& p,
  181. enable_if_t<
  182. is_same<Property, InnerProperty>::value
  183. >* = 0,
  184. enable_if_t<
  185. can_prefer<const Executor&, const InnerProperty&>::value
  186. >* = 0)
  187. #if !defined(BOOST_ASIO_MSVC) \
  188. && !defined(__clang__) // Clang crashes if noexcept is used here.
  189. noexcept(is_nothrow_prefer<const Executor&, const InnerProperty&>::value)
  190. #endif // !defined(BOOST_ASIO_MSVC)
  191. // && !defined(__clang__)
  192. {
  193. return boost::asio::prefer(ex, p.property);
  194. }
  195. template <typename Executor, typename Property>
  196. friend constexpr
  197. query_result_t<const Executor&, const InnerProperty&>
  198. query(const Executor& ex, const prefer_only<Property>& p,
  199. enable_if_t<
  200. is_same<Property, InnerProperty>::value
  201. >* = 0,
  202. enable_if_t<
  203. can_query<const Executor&, const InnerProperty&>::value
  204. >* = 0)
  205. #if !defined(BOOST_ASIO_MSVC) \
  206. && !defined(__clang__) // Clang crashes if noexcept is used here.
  207. noexcept(is_nothrow_query<const Executor&, const InnerProperty&>::value)
  208. #endif // !defined(BOOST_ASIO_MSVC)
  209. // && !defined(__clang__)
  210. {
  211. return boost::asio::query(ex, p.property);
  212. }
  213. };
  214. #if defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  215. && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  216. template <typename InnerProperty> template <typename E, typename T>
  217. const T prefer_only<InnerProperty>::static_query_v;
  218. #endif // defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  219. // && defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  220. } // namespace execution
  221. template <typename T, typename InnerProperty>
  222. struct is_applicable_property<T, execution::prefer_only<InnerProperty>>
  223. : is_applicable_property<T, InnerProperty>
  224. {
  225. };
  226. namespace traits {
  227. #if !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  228. || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  229. template <typename T, typename InnerProperty>
  230. struct static_query<T, execution::prefer_only<InnerProperty>> :
  231. static_query<T, const InnerProperty&>
  232. {
  233. };
  234. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  235. // || !defined(BOOST_ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  236. #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  237. template <typename T, typename InnerProperty>
  238. struct prefer_free_default<T, execution::prefer_only<InnerProperty>,
  239. enable_if_t<
  240. can_prefer<const T&, const InnerProperty&>::value
  241. >
  242. >
  243. {
  244. static constexpr bool is_valid = true;
  245. static constexpr bool is_noexcept =
  246. is_nothrow_prefer<const T&, const InnerProperty&>::value;
  247. typedef prefer_result_t<const T&, const InnerProperty&> result_type;
  248. };
  249. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  250. #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  251. template <typename T, typename InnerProperty>
  252. struct query_free<T, execution::prefer_only<InnerProperty>,
  253. enable_if_t<
  254. can_query<const T&, const InnerProperty&>::value
  255. >
  256. >
  257. {
  258. static constexpr bool is_valid = true;
  259. static constexpr bool is_noexcept =
  260. is_nothrow_query<const T&, const InnerProperty&>::value;
  261. typedef query_result_t<const T&, const InnerProperty&> result_type;
  262. };
  263. #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  264. } // namespace traits
  265. #endif // defined(GENERATING_DOCUMENTATION)
  266. } // namespace asio
  267. } // namespace boost
  268. #include <boost/asio/detail/pop_options.hpp>
  269. #endif // BOOST_ASIO_EXECUTION_PREFER_ONLY_HPP