prefer_only.hpp 8.6 KB

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