query.hpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. //
  2. // query.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_QUERY_HPP
  11. #define BOOST_ASIO_QUERY_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/traits/query_member.hpp>
  19. #include <boost/asio/traits/query_free.hpp>
  20. #include <boost/asio/traits/static_query.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. #if defined(GENERATING_DOCUMENTATION)
  23. namespace boost {
  24. namespace asio {
  25. /// A customisation point that queries the value of a property.
  26. /**
  27. * The name <tt>query</tt> denotes a customization point object. The
  28. * expression <tt>boost::asio::query(E, P)</tt> for some
  29. * subexpressions <tt>E</tt> and <tt>P</tt> (with types <tt>T =
  30. * decay_t<decltype(E)></tt> and <tt>Prop = decay_t<decltype(P)></tt>) is
  31. * expression-equivalent to:
  32. *
  33. * @li If <tt>is_applicable_property_v<T, Prop></tt> is not a well-formed
  34. * constant expression with value <tt>true</tt>, <tt>boost::asio::query(E,
  35. * P)</tt> is ill-formed.
  36. *
  37. * @li Otherwise, <tt>Prop::template static_query_v<T></tt> if the expression
  38. * <tt>Prop::template static_query_v<T></tt> is a well-formed constant
  39. * expression.
  40. *
  41. * @li Otherwise, <tt>(E).query(P)</tt> if the expression
  42. * <tt>(E).query(P)</tt> is well-formed.
  43. *
  44. * @li Otherwise, <tt>query(E, P)</tt> if the expression
  45. * <tt>query(E, P)</tt> is a valid expression with overload
  46. * resolution performed in a context that does not include the declaration
  47. * of the <tt>query</tt> customization point object.
  48. *
  49. * @li Otherwise, <tt>boost::asio::query(E, P)</tt> is ill-formed.
  50. */
  51. inline constexpr unspecified query = unspecified;
  52. /// A type trait that determines whether a @c query expression is well-formed.
  53. /**
  54. * Class template @c can_query is a trait that is derived from
  55. * @c true_type if the expression <tt>boost::asio::query(std::declval<T>(),
  56. * std::declval<Property>())</tt> is well formed; otherwise @c false_type.
  57. */
  58. template <typename T, typename Property>
  59. struct can_query :
  60. integral_constant<bool, automatically_determined>
  61. {
  62. };
  63. /// A type trait that determines whether a @c query expression will
  64. /// not throw.
  65. /**
  66. * Class template @c is_nothrow_query is a trait that is derived from
  67. * @c true_type if the expression <tt>boost::asio::query(std::declval<T>(),
  68. * std::declval<Property>())</tt> is @c noexcept; otherwise @c false_type.
  69. */
  70. template <typename T, typename Property>
  71. struct is_nothrow_query :
  72. integral_constant<bool, automatically_determined>
  73. {
  74. };
  75. /// A type trait that determines the result type of a @c query expression.
  76. /**
  77. * Class template @c query_result is a trait that determines the result
  78. * type of the expression <tt>boost::asio::query(std::declval<T>(),
  79. * std::declval<Property>())</tt>.
  80. */
  81. template <typename T, typename Property>
  82. struct query_result
  83. {
  84. /// The result of the @c query expression.
  85. typedef automatically_determined type;
  86. };
  87. } // namespace asio
  88. } // namespace boost
  89. #else // defined(GENERATING_DOCUMENTATION)
  90. namespace asio_query_fn {
  91. using boost::asio::conditional;
  92. using boost::asio::decay;
  93. using boost::asio::declval;
  94. using boost::asio::enable_if;
  95. using boost::asio::is_applicable_property;
  96. using boost::asio::traits::query_free;
  97. using boost::asio::traits::query_member;
  98. using boost::asio::traits::static_query;
  99. void query();
  100. enum overload_type
  101. {
  102. static_value,
  103. call_member,
  104. call_free,
  105. ill_formed
  106. };
  107. template <typename Impl, typename T, typename Properties,
  108. typename = void, typename = void, typename = void, typename = void>
  109. struct call_traits
  110. {
  111. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  112. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  113. typedef void result_type;
  114. };
  115. template <typename Impl, typename T, typename Property>
  116. struct call_traits<Impl, T, void(Property),
  117. typename enable_if<
  118. is_applicable_property<
  119. typename decay<T>::type,
  120. typename decay<Property>::type
  121. >::value
  122. >::type,
  123. typename enable_if<
  124. static_query<T, Property>::is_valid
  125. >::type> :
  126. static_query<T, Property>
  127. {
  128. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = static_value);
  129. };
  130. template <typename Impl, typename T, typename Property>
  131. struct call_traits<Impl, T, void(Property),
  132. typename enable_if<
  133. is_applicable_property<
  134. typename decay<T>::type,
  135. typename decay<Property>::type
  136. >::value
  137. >::type,
  138. typename enable_if<
  139. !static_query<T, Property>::is_valid
  140. >::type,
  141. typename enable_if<
  142. query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  143. >::type> :
  144. query_member<typename Impl::template proxy<T>::type, Property>
  145. {
  146. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
  147. };
  148. template <typename Impl, typename T, typename Property>
  149. struct call_traits<Impl, T, void(Property),
  150. typename enable_if<
  151. is_applicable_property<
  152. typename decay<T>::type,
  153. typename decay<Property>::type
  154. >::value
  155. >::type,
  156. typename enable_if<
  157. !static_query<T, Property>::is_valid
  158. >::type,
  159. typename enable_if<
  160. !query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  161. >::type,
  162. typename enable_if<
  163. query_free<T, Property>::is_valid
  164. >::type> :
  165. query_free<T, Property>
  166. {
  167. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
  168. };
  169. struct impl
  170. {
  171. template <typename T>
  172. struct proxy
  173. {
  174. #if defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  175. struct type
  176. {
  177. template <typename P>
  178. auto query(BOOST_ASIO_MOVE_ARG(P) p)
  179. noexcept(
  180. noexcept(
  181. declval<typename conditional<true, T, P>::type>().query(
  182. BOOST_ASIO_MOVE_CAST(P)(p))
  183. )
  184. )
  185. -> decltype(
  186. declval<typename conditional<true, T, P>::type>().query(
  187. BOOST_ASIO_MOVE_CAST(P)(p))
  188. );
  189. };
  190. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  191. typedef T type;
  192. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  193. };
  194. template <typename T, typename Property>
  195. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  196. call_traits<impl, T, void(Property)>::overload == static_value,
  197. typename call_traits<impl, T, void(Property)>::result_type
  198. >::type
  199. operator()(
  200. BOOST_ASIO_MOVE_ARG(T),
  201. BOOST_ASIO_MOVE_ARG(Property)) const
  202. BOOST_ASIO_NOEXCEPT_IF((
  203. call_traits<impl, T, void(Property)>::is_noexcept))
  204. {
  205. return static_query<
  206. typename decay<T>::type,
  207. typename decay<Property>::type
  208. >::value();
  209. }
  210. template <typename T, typename Property>
  211. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  212. call_traits<impl, T, void(Property)>::overload == call_member,
  213. typename call_traits<impl, T, void(Property)>::result_type
  214. >::type
  215. operator()(
  216. BOOST_ASIO_MOVE_ARG(T) t,
  217. BOOST_ASIO_MOVE_ARG(Property) p) const
  218. BOOST_ASIO_NOEXCEPT_IF((
  219. call_traits<impl, T, void(Property)>::is_noexcept))
  220. {
  221. return BOOST_ASIO_MOVE_CAST(T)(t).query(BOOST_ASIO_MOVE_CAST(Property)(p));
  222. }
  223. template <typename T, typename Property>
  224. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  225. call_traits<impl, T, void(Property)>::overload == call_free,
  226. typename call_traits<impl, T, void(Property)>::result_type
  227. >::type
  228. operator()(
  229. BOOST_ASIO_MOVE_ARG(T) t,
  230. BOOST_ASIO_MOVE_ARG(Property) p) const
  231. BOOST_ASIO_NOEXCEPT_IF((
  232. call_traits<impl, T, void(Property)>::is_noexcept))
  233. {
  234. return query(BOOST_ASIO_MOVE_CAST(T)(t), BOOST_ASIO_MOVE_CAST(Property)(p));
  235. }
  236. };
  237. template <typename T = impl>
  238. struct static_instance
  239. {
  240. static const T instance;
  241. };
  242. template <typename T>
  243. const T static_instance<T>::instance = {};
  244. } // namespace asio_query_fn
  245. namespace boost {
  246. namespace asio {
  247. namespace {
  248. static BOOST_ASIO_CONSTEXPR const asio_query_fn::impl&
  249. query = asio_query_fn::static_instance<>::instance;
  250. } // namespace
  251. typedef asio_query_fn::impl query_t;
  252. template <typename T, typename Property>
  253. struct can_query :
  254. integral_constant<bool,
  255. asio_query_fn::call_traits<query_t, T, void(Property)>::overload !=
  256. asio_query_fn::ill_formed>
  257. {
  258. };
  259. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  260. template <typename T, typename Property>
  261. constexpr bool can_query_v
  262. = can_query<T, Property>::value;
  263. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  264. template <typename T, typename Property>
  265. struct is_nothrow_query :
  266. integral_constant<bool,
  267. asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept>
  268. {
  269. };
  270. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  271. template <typename T, typename Property>
  272. constexpr bool is_nothrow_query_v
  273. = is_nothrow_query<T, Property>::value;
  274. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  275. template <typename T, typename Property>
  276. struct query_result
  277. {
  278. typedef typename asio_query_fn::call_traits<
  279. query_t, T, void(Property)>::result_type type;
  280. };
  281. } // namespace asio
  282. } // namespace boost
  283. #endif // defined(GENERATING_DOCUMENTATION)
  284. #include <boost/asio/detail/pop_options.hpp>
  285. #endif // BOOST_ASIO_QUERY_HPP