prefer_only.hpp 9.4 KB

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