prefer_only.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. //
  2. // execution/prefer_only.hpp
  3. // ~~~~~~~~~~~~~~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2022 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. ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  54. };
  55. template <typename InnerProperty>
  56. struct prefer_only_is_preferable<InnerProperty,
  57. typename enable_if<
  58. InnerProperty::is_preferable
  59. >::type>
  60. {
  61. ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  62. };
  63. template <typename InnerProperty, typename = void>
  64. struct prefer_only_polymorphic_query_result_type
  65. {
  66. };
  67. template <typename InnerProperty>
  68. struct prefer_only_polymorphic_query_result_type<InnerProperty,
  69. typename void_type<
  70. typename InnerProperty::polymorphic_query_result_type
  71. >::type>
  72. {
  73. typedef typename InnerProperty::polymorphic_query_result_type
  74. polymorphic_query_result_type;
  75. };
  76. template <typename InnerProperty, typename = void>
  77. struct prefer_only_property
  78. {
  79. InnerProperty property;
  80. prefer_only_property(const InnerProperty& p)
  81. : property(p)
  82. {
  83. }
  84. };
  85. #if defined(ASIO_HAS_DECLTYPE) \
  86. && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)
  87. template <typename InnerProperty>
  88. struct prefer_only_property<InnerProperty,
  89. typename void_type<
  90. decltype(asio::declval<const InnerProperty>().value())
  91. >::type>
  92. {
  93. InnerProperty property;
  94. prefer_only_property(const InnerProperty& p)
  95. : property(p)
  96. {
  97. }
  98. ASIO_CONSTEXPR auto value() const
  99. ASIO_NOEXCEPT_IF((
  100. noexcept(asio::declval<const InnerProperty>().value())))
  101. -> decltype(asio::declval<const InnerProperty>().value())
  102. {
  103. return property.value();
  104. }
  105. };
  106. #else // defined(ASIO_HAS_DECLTYPE)
  107. // && 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. typename enable_if<
  131. sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1
  132. && !is_same<typename InnerProperty::polymorphic_query_result_type,
  133. void>::value
  134. >::type>
  135. {
  136. InnerProperty property;
  137. prefer_only_property(const InnerProperty& p)
  138. : property(p)
  139. {
  140. }
  141. ASIO_CONSTEXPR typename InnerProperty::polymorphic_query_result_type
  142. value() const
  143. {
  144. return property.value();
  145. }
  146. };
  147. #endif // defined(ASIO_HAS_DECLTYPE)
  148. // && 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. ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
  157. ASIO_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 ASIO_CONSTEXPR
  165. typename traits::static_query<T, InnerProperty>::result_type
  166. static_query()
  167. ASIO_NOEXCEPT_IF((
  168. 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 ASIO_CONSTEXPR const T static_query_v
  174. = prefer_only::static_query<E>();
  175. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  176. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  177. template <typename Executor, typename Property>
  178. friend ASIO_CONSTEXPR
  179. typename prefer_result<const Executor&, const InnerProperty&>::type
  180. prefer(const Executor& ex, const prefer_only<Property>& p,
  181. typename enable_if<
  182. is_same<Property, InnerProperty>::value
  183. >::type* = 0,
  184. typename enable_if<
  185. can_prefer<const Executor&, const InnerProperty&>::value
  186. >::type* = 0)
  187. #if !defined(ASIO_MSVC) \
  188. && !defined(__clang__) // Clang crashes if noexcept is used here.
  189. ASIO_NOEXCEPT_IF((
  190. is_nothrow_prefer<const Executor&, const InnerProperty&>::value))
  191. #endif // !defined(ASIO_MSVC)
  192. // && !defined(__clang__)
  193. {
  194. return asio::prefer(ex, p.property);
  195. }
  196. template <typename Executor, typename Property>
  197. friend ASIO_CONSTEXPR
  198. typename query_result<const Executor&, const InnerProperty&>::type
  199. query(const Executor& ex, const prefer_only<Property>& p,
  200. typename enable_if<
  201. is_same<Property, InnerProperty>::value
  202. >::type* = 0,
  203. typename enable_if<
  204. can_query<const Executor&, const InnerProperty&>::value
  205. >::type* = 0)
  206. #if !defined(ASIO_MSVC) \
  207. && !defined(__clang__) // Clang crashes if noexcept is used here.
  208. ASIO_NOEXCEPT_IF((
  209. is_nothrow_query<const Executor&, const InnerProperty&>::value))
  210. #endif // !defined(ASIO_MSVC)
  211. // && !defined(__clang__)
  212. {
  213. return asio::query(ex, p.property);
  214. }
  215. };
  216. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  217. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  218. template <typename InnerProperty> template <typename E, typename T>
  219. const T prefer_only<InnerProperty>::static_query_v;
  220. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  221. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  222. } // namespace execution
  223. template <typename T, typename InnerProperty>
  224. struct is_applicable_property<T, execution::prefer_only<InnerProperty> >
  225. : is_applicable_property<T, InnerProperty>
  226. {
  227. };
  228. namespace traits {
  229. #if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  230. || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  231. template <typename T, typename InnerProperty>
  232. struct static_query<T, execution::prefer_only<InnerProperty> > :
  233. static_query<T, const InnerProperty&>
  234. {
  235. };
  236. #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  237. // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  238. #if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  239. template <typename T, typename InnerProperty>
  240. struct prefer_free_default<T, execution::prefer_only<InnerProperty>,
  241. typename enable_if<
  242. can_prefer<const T&, const InnerProperty&>::value
  243. >::type>
  244. {
  245. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  246. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  247. (is_nothrow_prefer<const T&, const InnerProperty&>::value));
  248. typedef typename prefer_result<const T&,
  249. const InnerProperty&>::type result_type;
  250. };
  251. #endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)
  252. #if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  253. template <typename T, typename InnerProperty>
  254. struct query_free<T, execution::prefer_only<InnerProperty>,
  255. typename enable_if<
  256. can_query<const T&, const InnerProperty&>::value
  257. >::type>
  258. {
  259. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  260. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  261. (is_nothrow_query<const T&, const InnerProperty&>::value));
  262. typedef typename query_result<const T&,
  263. const InnerProperty&>::type result_type;
  264. };
  265. #endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  266. } // namespace traits
  267. #endif // defined(GENERATING_DOCUMENTATION)
  268. } // namespace asio
  269. #include "asio/detail/pop_options.hpp"
  270. #endif // ASIO_EXECUTION_PREFER_ONLY_HPP