require.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575
  1. //
  2. // require.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_REQUIRE_HPP
  11. #define BOOST_ASIO_REQUIRE_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/require_member.hpp>
  19. #include <boost/asio/traits/require_free.hpp>
  20. #include <boost/asio/traits/static_require.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 applies a concept-preserving property to an
  26. /// object.
  27. /**
  28. * The name <tt>require</tt> denotes a customisation point object. The
  29. * expression <tt>boost::asio::require(E, P0, Pn...)</tt> for some
  30. * subexpressions <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt>
  31. * represents <tt>N</tt> subexpressions (where <tt>N</tt> is 0 or more, and with
  32. * types <tt>T = decay_t<decltype(E)></tt> and <tt>Prop0 =
  33. * decay_t<decltype(P0)></tt>) is expression-equivalent to:
  34. *
  35. * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_requirable</tt> is
  36. * not a well-formed constant expression with value <tt>true</tt>,
  37. * <tt>boost::asio::require(E, P0, Pn...)</tt> is ill-formed.
  38. *
  39. * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt> and the expression
  40. * <tt>Prop0::template static_query_v<T> == Prop0::value()</tt> is a
  41. * well-formed constant expression with value <tt>true</tt>.
  42. *
  43. * @li Otherwise, <tt>(E).require(P0)</tt> if <tt>N == 0</tt> and the expression
  44. * <tt>(E).require(P0)</tt> is a valid expression.
  45. *
  46. * @li Otherwise, <tt>require(E, P0)</tt> if <tt>N == 0</tt> and the expression
  47. * <tt>require(E, P0)</tt> is a valid expression with overload resolution
  48. * performed in a context that does not include the declaration of the
  49. * <tt>require</tt> customization point object.
  50. *
  51. * @li Otherwise,
  52. * <tt>boost::asio::require(boost::asio::require(E, P0), Pn...)</tt>
  53. * if <tt>N > 0</tt> and the expression
  54. * <tt>boost::asio::require(boost::asio::require(E, P0), Pn...)</tt>
  55. * is a valid expression.
  56. *
  57. * @li Otherwise, <tt>boost::asio::require(E, P0, Pn...)</tt> is ill-formed.
  58. */
  59. inline constexpr unspecified require = unspecified;
  60. /// A type trait that determines whether a @c require expression is well-formed.
  61. /**
  62. * Class template @c can_require is a trait that is derived from
  63. * @c true_type if the expression <tt>boost::asio::require(std::declval<T>(),
  64. * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type.
  65. */
  66. template <typename T, typename... Properties>
  67. struct can_require :
  68. integral_constant<bool, automatically_determined>
  69. {
  70. };
  71. /// A type trait that determines whether a @c require expression will not throw.
  72. /**
  73. * Class template @c is_nothrow_require is a trait that is derived from
  74. * @c true_type if the expression <tt>boost::asio::require(std::declval<T>(),
  75. * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type.
  76. */
  77. template <typename T, typename... Properties>
  78. struct is_nothrow_require :
  79. integral_constant<bool, automatically_determined>
  80. {
  81. };
  82. /// A type trait that determines the result type of a @c require expression.
  83. /**
  84. * Class template @c require_result is a trait that determines the result
  85. * type of the expression <tt>boost::asio::require(std::declval<T>(),
  86. * std::declval<Properties>()...)</tt>.
  87. */
  88. template <typename T, typename... Properties>
  89. struct require_result
  90. {
  91. /// The result of the @c require expression.
  92. typedef automatically_determined type;
  93. };
  94. } // namespace asio
  95. } // namespace boost
  96. #else // defined(GENERATING_DOCUMENTATION)
  97. namespace asio_require_fn {
  98. using boost::asio::conditional;
  99. using boost::asio::decay;
  100. using boost::asio::declval;
  101. using boost::asio::enable_if;
  102. using boost::asio::is_applicable_property;
  103. using boost::asio::traits::require_free;
  104. using boost::asio::traits::require_member;
  105. using boost::asio::traits::static_require;
  106. void require();
  107. enum overload_type
  108. {
  109. identity,
  110. call_member,
  111. call_free,
  112. two_props,
  113. n_props,
  114. ill_formed
  115. };
  116. template <typename Impl, typename T, typename Properties, typename = void,
  117. typename = void, typename = void, typename = void, typename = void>
  118. struct call_traits
  119. {
  120. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  121. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  122. typedef void result_type;
  123. };
  124. template <typename Impl, typename T, typename Property>
  125. struct call_traits<Impl, T, void(Property),
  126. typename enable_if<
  127. is_applicable_property<
  128. typename decay<T>::type,
  129. typename decay<Property>::type
  130. >::value
  131. >::type,
  132. typename enable_if<
  133. decay<Property>::type::is_requirable
  134. >::type,
  135. typename enable_if<
  136. static_require<T, Property>::is_valid
  137. >::type>
  138. {
  139. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
  140. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  141. #if defined(BOOST_ASIO_HAS_MOVE)
  142. typedef BOOST_ASIO_MOVE_ARG(T) result_type;
  143. #else // defined(BOOST_ASIO_HAS_MOVE)
  144. typedef BOOST_ASIO_MOVE_ARG(typename decay<T>::type) result_type;
  145. #endif // defined(BOOST_ASIO_HAS_MOVE)
  146. };
  147. template <typename Impl, typename T, typename Property>
  148. struct call_traits<Impl, T, void(Property),
  149. typename enable_if<
  150. is_applicable_property<
  151. typename decay<T>::type,
  152. typename decay<Property>::type
  153. >::value
  154. >::type,
  155. typename enable_if<
  156. decay<Property>::type::is_requirable
  157. >::type,
  158. typename enable_if<
  159. !static_require<T, Property>::is_valid
  160. >::type,
  161. typename enable_if<
  162. require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  163. >::type> :
  164. require_member<typename Impl::template proxy<T>::type, Property>
  165. {
  166. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);
  167. };
  168. template <typename Impl, typename T, typename Property>
  169. struct call_traits<Impl, T, void(Property),
  170. typename enable_if<
  171. is_applicable_property<
  172. typename decay<T>::type,
  173. typename decay<Property>::type
  174. >::value
  175. >::type,
  176. typename enable_if<
  177. decay<Property>::type::is_requirable
  178. >::type,
  179. typename enable_if<
  180. !static_require<T, Property>::is_valid
  181. >::type,
  182. typename enable_if<
  183. !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  184. >::type,
  185. typename enable_if<
  186. require_free<T, Property>::is_valid
  187. >::type> :
  188. require_free<T, Property>
  189. {
  190. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);
  191. };
  192. template <typename Impl, typename T, typename P0, typename P1>
  193. struct call_traits<Impl, T, void(P0, P1),
  194. typename enable_if<
  195. call_traits<Impl, T, void(P0)>::overload != ill_formed
  196. >::type,
  197. typename enable_if<
  198. call_traits<
  199. Impl,
  200. typename call_traits<Impl, T, void(P0)>::result_type,
  201. void(P1)
  202. >::overload != ill_formed
  203. >::type>
  204. {
  205. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props);
  206. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  207. (
  208. call_traits<Impl, T, void(P0)>::is_noexcept
  209. &&
  210. call_traits<
  211. Impl,
  212. typename call_traits<Impl, T, void(P0)>::result_type,
  213. void(P1)
  214. >::is_noexcept
  215. ));
  216. typedef typename decay<
  217. typename call_traits<
  218. Impl,
  219. typename call_traits<Impl, T, void(P0)>::result_type,
  220. void(P1)
  221. >::result_type
  222. >::type result_type;
  223. };
  224. template <typename Impl, typename T, typename P0,
  225. typename P1, typename BOOST_ASIO_ELLIPSIS PN>
  226. struct call_traits<Impl, T, void(P0, P1, PN BOOST_ASIO_ELLIPSIS),
  227. typename enable_if<
  228. call_traits<Impl, T, void(P0)>::overload != ill_formed
  229. >::type,
  230. typename enable_if<
  231. call_traits<
  232. Impl,
  233. typename call_traits<Impl, T, void(P0)>::result_type,
  234. void(P1, PN BOOST_ASIO_ELLIPSIS)
  235. >::overload != ill_formed
  236. >::type>
  237. {
  238. BOOST_ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props);
  239. BOOST_ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  240. (
  241. call_traits<Impl, T, void(P0)>::is_noexcept
  242. &&
  243. call_traits<
  244. Impl,
  245. typename call_traits<Impl, T, void(P0)>::result_type,
  246. void(P1, PN BOOST_ASIO_ELLIPSIS)
  247. >::is_noexcept
  248. ));
  249. typedef typename decay<
  250. typename call_traits<
  251. Impl,
  252. typename call_traits<Impl, T, void(P0)>::result_type,
  253. void(P1, PN BOOST_ASIO_ELLIPSIS)
  254. >::result_type
  255. >::type result_type;
  256. };
  257. struct impl
  258. {
  259. template <typename T>
  260. struct proxy
  261. {
  262. #if defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  263. struct type
  264. {
  265. template <typename P>
  266. auto require(BOOST_ASIO_MOVE_ARG(P) p)
  267. noexcept(
  268. noexcept(
  269. declval<typename conditional<true, T, P>::type>().require(
  270. BOOST_ASIO_MOVE_CAST(P)(p))
  271. )
  272. )
  273. -> decltype(
  274. declval<typename conditional<true, T, P>::type>().require(
  275. BOOST_ASIO_MOVE_CAST(P)(p))
  276. );
  277. };
  278. #else // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  279. typedef T type;
  280. #endif // defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  281. };
  282. template <typename T, typename Property>
  283. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  284. call_traits<impl, T, void(Property)>::overload == identity,
  285. typename call_traits<impl, T, void(Property)>::result_type
  286. >::type
  287. operator()(
  288. BOOST_ASIO_MOVE_ARG(T) t,
  289. BOOST_ASIO_MOVE_ARG(Property)) const
  290. BOOST_ASIO_NOEXCEPT_IF((
  291. call_traits<impl, T, void(Property)>::is_noexcept))
  292. {
  293. return BOOST_ASIO_MOVE_CAST(T)(t);
  294. }
  295. template <typename T, typename Property>
  296. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  297. call_traits<impl, T, void(Property)>::overload == call_member,
  298. typename call_traits<impl, T, void(Property)>::result_type
  299. >::type
  300. operator()(
  301. BOOST_ASIO_MOVE_ARG(T) t,
  302. BOOST_ASIO_MOVE_ARG(Property) p) const
  303. BOOST_ASIO_NOEXCEPT_IF((
  304. call_traits<impl, T, void(Property)>::is_noexcept))
  305. {
  306. return BOOST_ASIO_MOVE_CAST(T)(t).require(
  307. BOOST_ASIO_MOVE_CAST(Property)(p));
  308. }
  309. template <typename T, typename Property>
  310. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  311. call_traits<impl, T, void(Property)>::overload == call_free,
  312. typename call_traits<impl, T, void(Property)>::result_type
  313. >::type
  314. operator()(
  315. BOOST_ASIO_MOVE_ARG(T) t,
  316. BOOST_ASIO_MOVE_ARG(Property) p) const
  317. BOOST_ASIO_NOEXCEPT_IF((
  318. call_traits<impl, T, void(Property)>::is_noexcept))
  319. {
  320. return require(
  321. BOOST_ASIO_MOVE_CAST(T)(t),
  322. BOOST_ASIO_MOVE_CAST(Property)(p));
  323. }
  324. template <typename T, typename P0, typename P1>
  325. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  326. call_traits<impl, T, void(P0, P1)>::overload == two_props,
  327. typename call_traits<impl, T, void(P0, P1)>::result_type
  328. >::type
  329. operator()(
  330. BOOST_ASIO_MOVE_ARG(T) t,
  331. BOOST_ASIO_MOVE_ARG(P0) p0,
  332. BOOST_ASIO_MOVE_ARG(P1) p1) const
  333. BOOST_ASIO_NOEXCEPT_IF((
  334. call_traits<impl, T, void(P0, P1)>::is_noexcept))
  335. {
  336. return (*this)(
  337. (*this)(
  338. BOOST_ASIO_MOVE_CAST(T)(t),
  339. BOOST_ASIO_MOVE_CAST(P0)(p0)),
  340. BOOST_ASIO_MOVE_CAST(P1)(p1));
  341. }
  342. template <typename T, typename P0, typename P1,
  343. typename BOOST_ASIO_ELLIPSIS PN>
  344. BOOST_ASIO_NODISCARD BOOST_ASIO_CONSTEXPR typename enable_if<
  345. call_traits<impl, T,
  346. void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::overload == n_props,
  347. typename call_traits<impl, T,
  348. void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::result_type
  349. >::type
  350. operator()(
  351. BOOST_ASIO_MOVE_ARG(T) t,
  352. BOOST_ASIO_MOVE_ARG(P0) p0,
  353. BOOST_ASIO_MOVE_ARG(P1) p1,
  354. BOOST_ASIO_MOVE_ARG(PN) BOOST_ASIO_ELLIPSIS pn) const
  355. BOOST_ASIO_NOEXCEPT_IF((
  356. call_traits<impl, T, void(P0, P1, PN BOOST_ASIO_ELLIPSIS)>::is_noexcept))
  357. {
  358. return (*this)(
  359. (*this)(
  360. BOOST_ASIO_MOVE_CAST(T)(t),
  361. BOOST_ASIO_MOVE_CAST(P0)(p0)),
  362. BOOST_ASIO_MOVE_CAST(P1)(p1),
  363. BOOST_ASIO_MOVE_CAST(PN)(pn) BOOST_ASIO_ELLIPSIS);
  364. }
  365. };
  366. template <typename T = impl>
  367. struct static_instance
  368. {
  369. static const T instance;
  370. };
  371. template <typename T>
  372. const T static_instance<T>::instance = {};
  373. } // namespace asio_require_fn
  374. namespace boost {
  375. namespace asio {
  376. namespace {
  377. static BOOST_ASIO_CONSTEXPR const asio_require_fn::impl&
  378. require = asio_require_fn::static_instance<>::instance;
  379. } // namespace
  380. typedef asio_require_fn::impl require_t;
  381. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  382. template <typename T, typename... Properties>
  383. struct can_require :
  384. integral_constant<bool,
  385. asio_require_fn::call_traits<
  386. require_t, T, void(Properties...)>::overload
  387. != asio_require_fn::ill_formed>
  388. {
  389. };
  390. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  391. template <typename T, typename P0 = void,
  392. typename P1 = void, typename P2 = void>
  393. struct can_require :
  394. integral_constant<bool,
  395. asio_require_fn::call_traits<require_t, T, void(P0, P1, P2)>::overload
  396. != asio_require_fn::ill_formed>
  397. {
  398. };
  399. template <typename T, typename P0, typename P1>
  400. struct can_require<T, P0, P1> :
  401. integral_constant<bool,
  402. asio_require_fn::call_traits<require_t, T, void(P0, P1)>::overload
  403. != asio_require_fn::ill_formed>
  404. {
  405. };
  406. template <typename T, typename P0>
  407. struct can_require<T, P0> :
  408. integral_constant<bool,
  409. asio_require_fn::call_traits<require_t, T, void(P0)>::overload
  410. != asio_require_fn::ill_formed>
  411. {
  412. };
  413. template <typename T>
  414. struct can_require<T> :
  415. false_type
  416. {
  417. };
  418. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  419. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  420. template <typename T, typename BOOST_ASIO_ELLIPSIS Properties>
  421. constexpr bool can_require_v
  422. = can_require<T, Properties BOOST_ASIO_ELLIPSIS>::value;
  423. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  424. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  425. template <typename T, typename... Properties>
  426. struct is_nothrow_require :
  427. integral_constant<bool,
  428. asio_require_fn::call_traits<
  429. require_t, T, void(Properties...)>::is_noexcept>
  430. {
  431. };
  432. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  433. template <typename T, typename P0 = void,
  434. typename P1 = void, typename P2 = void>
  435. struct is_nothrow_require :
  436. integral_constant<bool,
  437. asio_require_fn::call_traits<
  438. require_t, T, void(P0, P1, P2)>::is_noexcept>
  439. {
  440. };
  441. template <typename T, typename P0, typename P1>
  442. struct is_nothrow_require<T, P0, P1> :
  443. integral_constant<bool,
  444. asio_require_fn::call_traits<
  445. require_t, T, void(P0, P1)>::is_noexcept>
  446. {
  447. };
  448. template <typename T, typename P0>
  449. struct is_nothrow_require<T, P0> :
  450. integral_constant<bool,
  451. asio_require_fn::call_traits<
  452. require_t, T, void(P0)>::is_noexcept>
  453. {
  454. };
  455. template <typename T>
  456. struct is_nothrow_require<T> :
  457. false_type
  458. {
  459. };
  460. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  461. #if defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  462. template <typename T, typename BOOST_ASIO_ELLIPSIS Properties>
  463. constexpr bool is_nothrow_require_v
  464. = is_nothrow_require<T, Properties BOOST_ASIO_ELLIPSIS>::value;
  465. #endif // defined(BOOST_ASIO_HAS_VARIABLE_TEMPLATES)
  466. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  467. template <typename T, typename... Properties>
  468. struct require_result
  469. {
  470. typedef typename asio_require_fn::call_traits<
  471. require_t, T, void(Properties...)>::result_type type;
  472. };
  473. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  474. template <typename T, typename P0 = void,
  475. typename P1 = void, typename P2 = void>
  476. struct require_result
  477. {
  478. typedef typename asio_require_fn::call_traits<
  479. require_t, T, void(P0, P1, P2)>::result_type type;
  480. };
  481. template <typename T, typename P0, typename P1>
  482. struct require_result<T, P0, P1>
  483. {
  484. typedef typename asio_require_fn::call_traits<
  485. require_t, T, void(P0, P1)>::result_type type;
  486. };
  487. template <typename T, typename P0>
  488. struct require_result<T, P0>
  489. {
  490. typedef typename asio_require_fn::call_traits<
  491. require_t, T, void(P0)>::result_type type;
  492. };
  493. template <typename T>
  494. struct require_result<T>
  495. {
  496. };
  497. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  498. } // namespace asio
  499. } // namespace boost
  500. #endif // defined(GENERATING_DOCUMENTATION)
  501. #include <boost/asio/detail/pop_options.hpp>
  502. #endif // BOOST_ASIO_REQUIRE_HPP