query.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. //
  2. // query.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_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 boost_asio_query_fn {
  91. using boost::asio::conditional_t;
  92. using boost::asio::decay_t;
  93. using boost::asio::declval;
  94. using boost::asio::enable_if_t;
  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. static constexpr overload_type overload = ill_formed;
  112. 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. enable_if_t<
  118. is_applicable_property<
  119. decay_t<T>,
  120. decay_t<Property>
  121. >::value
  122. >,
  123. enable_if_t<
  124. static_query<T, Property>::is_valid
  125. >> :
  126. static_query<T, Property>
  127. {
  128. 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. enable_if_t<
  133. is_applicable_property<
  134. decay_t<T>,
  135. decay_t<Property>
  136. >::value
  137. >,
  138. enable_if_t<
  139. !static_query<T, Property>::is_valid
  140. >,
  141. enable_if_t<
  142. query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  143. >> :
  144. query_member<typename Impl::template proxy<T>::type, Property>
  145. {
  146. 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. enable_if_t<
  151. is_applicable_property<
  152. decay_t<T>,
  153. decay_t<Property>
  154. >::value
  155. >,
  156. enable_if_t<
  157. !static_query<T, Property>::is_valid
  158. >,
  159. enable_if_t<
  160. !query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  161. >,
  162. enable_if_t<
  163. query_free<T, Property>::is_valid
  164. >> :
  165. query_free<T, Property>
  166. {
  167. 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(P&& p)
  179. noexcept(
  180. noexcept(
  181. declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
  182. )
  183. )
  184. -> decltype(
  185. declval<conditional_t<true, T, P>>().query(static_cast<P&&>(p))
  186. );
  187. };
  188. #else // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  189. typedef T type;
  190. #endif // defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  191. };
  192. template <typename T, typename Property>
  193. BOOST_ASIO_NODISCARD constexpr enable_if_t<
  194. call_traits<impl, T, void(Property)>::overload == static_value,
  195. typename call_traits<impl, T, void(Property)>::result_type
  196. >
  197. operator()(T&&, Property&&) const
  198. noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
  199. {
  200. return static_query<decay_t<T>, decay_t<Property>>::value();
  201. }
  202. template <typename T, typename Property>
  203. BOOST_ASIO_NODISCARD constexpr enable_if_t<
  204. call_traits<impl, T, void(Property)>::overload == call_member,
  205. typename call_traits<impl, T, void(Property)>::result_type
  206. >
  207. operator()(T&& t, Property&& p) const
  208. noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
  209. {
  210. return static_cast<T&&>(t).query(static_cast<Property&&>(p));
  211. }
  212. template <typename T, typename Property>
  213. BOOST_ASIO_NODISCARD constexpr enable_if_t<
  214. call_traits<impl, T, void(Property)>::overload == call_free,
  215. typename call_traits<impl, T, void(Property)>::result_type
  216. >
  217. operator()(T&& t, Property&& p) const
  218. noexcept(call_traits<impl, T, void(Property)>::is_noexcept)
  219. {
  220. return query(static_cast<T&&>(t), static_cast<Property&&>(p));
  221. }
  222. };
  223. template <typename T = impl>
  224. struct static_instance
  225. {
  226. static const T instance;
  227. };
  228. template <typename T>
  229. const T static_instance<T>::instance = {};
  230. } // namespace boost_asio_query_fn
  231. namespace boost {
  232. namespace asio {
  233. namespace {
  234. static constexpr const boost_asio_query_fn::impl&
  235. query = boost_asio_query_fn::static_instance<>::instance;
  236. } // namespace
  237. typedef boost_asio_query_fn::impl query_t;
  238. template <typename T, typename Property>
  239. struct can_query :
  240. integral_constant<bool,
  241. boost_asio_query_fn::call_traits<query_t, T, void(Property)>::overload !=
  242. boost_asio_query_fn::ill_formed>
  243. {
  244. };
  245. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  246. template <typename T, typename Property>
  247. constexpr bool can_query_v = can_query<T, Property>::value;
  248. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  249. template <typename T, typename Property>
  250. struct is_nothrow_query :
  251. integral_constant<bool,
  252. boost_asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept>
  253. {
  254. };
  255. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  256. template <typename T, typename Property>
  257. constexpr bool is_nothrow_query_v = is_nothrow_query<T, Property>::value;
  258. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  259. template <typename T, typename Property>
  260. struct query_result
  261. {
  262. typedef typename boost_asio_query_fn::call_traits<
  263. query_t, T, void(Property)>::result_type type;
  264. };
  265. template <typename T, typename Property>
  266. using query_result_t = typename query_result<T, Property>::type;
  267. } // namespace asio
  268. } // namespace boost
  269. #endif // defined(GENERATING_DOCUMENTATION)
  270. #include <boost/asio/detail/pop_options.hpp>
  271. #endif // BOOST_ASIO_QUERY_HPP