query.hpp 8.3 KB

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