prefer.hpp 16 KB

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