query.hpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. //
  2. // query.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_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;
  90. using asio::decay;
  91. using asio::declval;
  92. using asio::enable_if;
  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. ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  110. ASIO_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. typename enable_if<
  116. is_applicable_property<
  117. typename decay<T>::type,
  118. typename decay<Property>::type
  119. >::value
  120. >::type,
  121. typename enable_if<
  122. static_query<T, Property>::is_valid
  123. >::type> :
  124. static_query<T, Property>
  125. {
  126. ASIO_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. typename enable_if<
  131. is_applicable_property<
  132. typename decay<T>::type,
  133. typename decay<Property>::type
  134. >::value
  135. >::type,
  136. typename enable_if<
  137. !static_query<T, Property>::is_valid
  138. >::type,
  139. typename enable_if<
  140. query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  141. >::type> :
  142. query_member<typename Impl::template proxy<T>::type, Property>
  143. {
  144. ASIO_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. typename enable_if<
  149. is_applicable_property<
  150. typename decay<T>::type,
  151. typename decay<Property>::type
  152. >::value
  153. >::type,
  154. typename enable_if<
  155. !static_query<T, Property>::is_valid
  156. >::type,
  157. typename enable_if<
  158. !query_member<typename Impl::template proxy<T>::type, Property>::is_valid
  159. >::type,
  160. typename enable_if<
  161. query_free<T, Property>::is_valid
  162. >::type> :
  163. query_free<T, Property>
  164. {
  165. ASIO_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(ASIO_MOVE_ARG(P) p)
  177. noexcept(
  178. noexcept(
  179. declval<typename conditional<true, T, P>::type>().query(
  180. ASIO_MOVE_CAST(P)(p))
  181. )
  182. )
  183. -> decltype(
  184. declval<typename conditional<true, T, P>::type>().query(
  185. ASIO_MOVE_CAST(P)(p))
  186. );
  187. };
  188. #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  189. typedef T type;
  190. #endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  191. };
  192. template <typename T, typename Property>
  193. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  194. call_traits<impl, T, void(Property)>::overload == static_value,
  195. typename call_traits<impl, T, void(Property)>::result_type
  196. >::type
  197. operator()(
  198. ASIO_MOVE_ARG(T),
  199. ASIO_MOVE_ARG(Property)) const
  200. ASIO_NOEXCEPT_IF((
  201. call_traits<impl, T, void(Property)>::is_noexcept))
  202. {
  203. return static_query<
  204. typename decay<T>::type,
  205. typename decay<Property>::type
  206. >::value();
  207. }
  208. template <typename T, typename Property>
  209. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  210. call_traits<impl, T, void(Property)>::overload == call_member,
  211. typename call_traits<impl, T, void(Property)>::result_type
  212. >::type
  213. operator()(
  214. ASIO_MOVE_ARG(T) t,
  215. ASIO_MOVE_ARG(Property) p) const
  216. ASIO_NOEXCEPT_IF((
  217. call_traits<impl, T, void(Property)>::is_noexcept))
  218. {
  219. return ASIO_MOVE_CAST(T)(t).query(ASIO_MOVE_CAST(Property)(p));
  220. }
  221. template <typename T, typename Property>
  222. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  223. call_traits<impl, T, void(Property)>::overload == call_free,
  224. typename call_traits<impl, T, void(Property)>::result_type
  225. >::type
  226. operator()(
  227. ASIO_MOVE_ARG(T) t,
  228. ASIO_MOVE_ARG(Property) p) const
  229. ASIO_NOEXCEPT_IF((
  230. call_traits<impl, T, void(Property)>::is_noexcept))
  231. {
  232. return query(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(Property)(p));
  233. }
  234. };
  235. template <typename T = impl>
  236. struct static_instance
  237. {
  238. static const T instance;
  239. };
  240. template <typename T>
  241. const T static_instance<T>::instance = {};
  242. } // namespace asio_query_fn
  243. namespace asio {
  244. namespace {
  245. static ASIO_CONSTEXPR const asio_query_fn::impl&
  246. query = asio_query_fn::static_instance<>::instance;
  247. } // namespace
  248. typedef asio_query_fn::impl query_t;
  249. template <typename T, typename Property>
  250. struct can_query :
  251. integral_constant<bool,
  252. asio_query_fn::call_traits<query_t, T, void(Property)>::overload !=
  253. asio_query_fn::ill_formed>
  254. {
  255. };
  256. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  257. template <typename T, typename Property>
  258. constexpr bool can_query_v
  259. = can_query<T, Property>::value;
  260. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  261. template <typename T, typename Property>
  262. struct is_nothrow_query :
  263. integral_constant<bool,
  264. asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept>
  265. {
  266. };
  267. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  268. template <typename T, typename Property>
  269. constexpr bool is_nothrow_query_v
  270. = is_nothrow_query<T, Property>::value;
  271. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  272. template <typename T, typename Property>
  273. struct query_result
  274. {
  275. typedef typename asio_query_fn::call_traits<
  276. query_t, T, void(Property)>::result_type type;
  277. };
  278. } // namespace asio
  279. #endif // defined(GENERATING_DOCUMENTATION)
  280. #include "asio/detail/pop_options.hpp"
  281. #endif // ASIO_QUERY_HPP