prefer.hpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. //
  2. // prefer.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_PREFER_HPP
  11. #define ASIO_PREFER_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/prefer_free.hpp"
  19. #include "asio/traits/prefer_member.hpp"
  20. #include "asio/traits/require_free.hpp"
  21. #include "asio/traits/require_member.hpp"
  22. #include "asio/traits/static_require.hpp"
  23. #include "asio/detail/push_options.hpp"
  24. #if defined(GENERATING_DOCUMENTATION)
  25. namespace asio {
  26. /// A customisation point that attempts to apply a property to an object.
  27. /**
  28. * The name <tt>prefer</tt> denotes a customisation point object. The
  29. * expression <tt>asio::prefer(E, P0, Pn...)</tt> for some subexpressions
  30. * <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt> represents <tt>N</tt>
  31. * subexpressions (where <tt>N</tt> is 0 or more, and with types <tt>T =
  32. * decay_t<decltype(E)></tt> and <tt>Prop0 = decay_t<decltype(P0)></tt>) is
  33. * expression-equivalent to:
  34. *
  35. * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_preferable</tt> is
  36. * not a well-formed constant expression with value <tt>true</tt>,
  37. * <tt>asio::prefer(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, <tt>(E).prefer(P0)</tt> if <tt>N == 0</tt> and the expression
  52. * <tt>(E).prefer(P0)</tt> is a valid expression.
  53. *
  54. * @li Otherwise, <tt>prefer(E, P0)</tt> if <tt>N == 0</tt> and the expression
  55. * <tt>prefer(E, P0)</tt> is a valid expression with overload resolution
  56. * performed in a context that does not include the declaration of the
  57. * <tt>prefer</tt> customization point object.
  58. *
  59. * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt>.
  60. *
  61. * @li Otherwise,
  62. * <tt>asio::prefer(asio::prefer(E, P0), Pn...)</tt>
  63. * if <tt>N > 0</tt> and the expression
  64. * <tt>asio::prefer(asio::prefer(E, P0), Pn...)</tt>
  65. * is a valid expression.
  66. *
  67. * @li Otherwise, <tt>asio::prefer(E, P0, Pn...)</tt> is ill-formed.
  68. */
  69. inline constexpr unspecified prefer = unspecified;
  70. /// A type trait that determines whether a @c prefer expression is well-formed.
  71. /**
  72. * Class template @c can_prefer is a trait that is derived from
  73. * @c true_type if the expression <tt>asio::prefer(std::declval<T>(),
  74. * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type.
  75. */
  76. template <typename T, typename... Properties>
  77. struct can_prefer :
  78. integral_constant<bool, automatically_determined>
  79. {
  80. };
  81. /// A type trait that determines whether a @c prefer expression will not throw.
  82. /**
  83. * Class template @c is_nothrow_prefer is a trait that is derived from
  84. * @c true_type if the expression <tt>asio::prefer(std::declval<T>(),
  85. * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type.
  86. */
  87. template <typename T, typename... Properties>
  88. struct is_nothrow_prefer :
  89. integral_constant<bool, automatically_determined>
  90. {
  91. };
  92. /// A type trait that determines the result type of a @c prefer expression.
  93. /**
  94. * Class template @c prefer_result is a trait that determines the result
  95. * type of the expression <tt>asio::prefer(std::declval<T>(),
  96. * std::declval<Properties>()...)</tt>.
  97. */
  98. template <typename T, typename... Properties>
  99. struct prefer_result
  100. {
  101. /// The result of the @c prefer expression.
  102. typedef automatically_determined type;
  103. };
  104. } // namespace asio
  105. #else // defined(GENERATING_DOCUMENTATION)
  106. namespace asio_prefer_fn {
  107. using asio::conditional;
  108. using asio::decay;
  109. using asio::declval;
  110. using asio::enable_if;
  111. using asio::is_applicable_property;
  112. using asio::traits::prefer_free;
  113. using asio::traits::prefer_member;
  114. using asio::traits::require_free;
  115. using asio::traits::require_member;
  116. using asio::traits::static_require;
  117. void prefer();
  118. void require();
  119. enum overload_type
  120. {
  121. identity,
  122. call_require_member,
  123. call_require_free,
  124. call_prefer_member,
  125. call_prefer_free,
  126. two_props,
  127. n_props,
  128. ill_formed
  129. };
  130. template <typename Impl, typename T, typename Properties,
  131. typename = void, typename = void, typename = void, typename = void,
  132. typename = void, typename = void, typename = void>
  133. struct call_traits
  134. {
  135. ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);
  136. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);
  137. typedef void result_type;
  138. };
  139. template <typename Impl, typename T, typename Property>
  140. struct call_traits<Impl, T, void(Property),
  141. typename enable_if<
  142. is_applicable_property<
  143. typename decay<T>::type,
  144. typename decay<Property>::type
  145. >::value
  146. >::type,
  147. typename enable_if<
  148. decay<Property>::type::is_preferable
  149. >::type,
  150. typename enable_if<
  151. static_require<T, Property>::is_valid
  152. >::type>
  153. {
  154. ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
  155. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  156. #if defined(ASIO_HAS_MOVE)
  157. typedef ASIO_MOVE_ARG(T) result_type;
  158. #else // defined(ASIO_HAS_MOVE)
  159. typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type;
  160. #endif // defined(ASIO_HAS_MOVE)
  161. };
  162. template <typename Impl, typename T, typename Property>
  163. struct call_traits<Impl, T, void(Property),
  164. typename enable_if<
  165. is_applicable_property<
  166. typename decay<T>::type,
  167. typename decay<Property>::type
  168. >::value
  169. >::type,
  170. typename enable_if<
  171. decay<Property>::type::is_preferable
  172. >::type,
  173. typename enable_if<
  174. !static_require<T, Property>::is_valid
  175. >::type,
  176. typename enable_if<
  177. require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  178. >::type> :
  179. require_member<typename Impl::template proxy<T>::type, Property>
  180. {
  181. ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member);
  182. };
  183. template <typename Impl, typename T, typename Property>
  184. struct call_traits<Impl, T, void(Property),
  185. typename enable_if<
  186. is_applicable_property<
  187. typename decay<T>::type,
  188. typename decay<Property>::type
  189. >::value
  190. >::type,
  191. typename enable_if<
  192. decay<Property>::type::is_preferable
  193. >::type,
  194. typename enable_if<
  195. !static_require<T, Property>::is_valid
  196. >::type,
  197. typename enable_if<
  198. !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  199. >::type,
  200. typename enable_if<
  201. require_free<T, Property>::is_valid
  202. >::type> :
  203. require_free<T, Property>
  204. {
  205. ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free);
  206. };
  207. template <typename Impl, typename T, typename Property>
  208. struct call_traits<Impl, T, void(Property),
  209. typename enable_if<
  210. is_applicable_property<
  211. typename decay<T>::type,
  212. typename decay<Property>::type
  213. >::value
  214. >::type,
  215. typename enable_if<
  216. decay<Property>::type::is_preferable
  217. >::type,
  218. typename enable_if<
  219. !static_require<T, Property>::is_valid
  220. >::type,
  221. typename enable_if<
  222. !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  223. >::type,
  224. typename enable_if<
  225. !require_free<T, Property>::is_valid
  226. >::type,
  227. typename enable_if<
  228. prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
  229. >::type> :
  230. prefer_member<typename Impl::template proxy<T>::type, Property>
  231. {
  232. ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member);
  233. };
  234. template <typename Impl, typename T, typename Property>
  235. struct call_traits<Impl, T, void(Property),
  236. typename enable_if<
  237. is_applicable_property<
  238. typename decay<T>::type,
  239. typename decay<Property>::type
  240. >::value
  241. >::type,
  242. typename enable_if<
  243. decay<Property>::type::is_preferable
  244. >::type,
  245. typename enable_if<
  246. !static_require<T, Property>::is_valid
  247. >::type,
  248. typename enable_if<
  249. !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  250. >::type,
  251. typename enable_if<
  252. !require_free<T, Property>::is_valid
  253. >::type,
  254. typename enable_if<
  255. !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
  256. >::type,
  257. typename enable_if<
  258. prefer_free<T, Property>::is_valid
  259. >::type> :
  260. prefer_free<T, Property>
  261. {
  262. ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free);
  263. };
  264. template <typename Impl, typename T, typename Property>
  265. struct call_traits<Impl, T, void(Property),
  266. typename enable_if<
  267. is_applicable_property<
  268. typename decay<T>::type,
  269. typename decay<Property>::type
  270. >::value
  271. >::type,
  272. typename enable_if<
  273. decay<Property>::type::is_preferable
  274. >::type,
  275. typename enable_if<
  276. !static_require<T, Property>::is_valid
  277. >::type,
  278. typename enable_if<
  279. !require_member<typename Impl::template proxy<T>::type, Property>::is_valid
  280. >::type,
  281. typename enable_if<
  282. !require_free<T, Property>::is_valid
  283. >::type,
  284. typename enable_if<
  285. !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid
  286. >::type,
  287. typename enable_if<
  288. !prefer_free<T, Property>::is_valid
  289. >::type>
  290. {
  291. ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);
  292. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  293. #if defined(ASIO_HAS_MOVE)
  294. typedef ASIO_MOVE_ARG(T) result_type;
  295. #else // defined(ASIO_HAS_MOVE)
  296. typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type;
  297. #endif // defined(ASIO_HAS_MOVE)
  298. };
  299. template <typename Impl, typename T, typename P0, typename P1>
  300. struct call_traits<Impl, T, void(P0, P1),
  301. typename enable_if<
  302. call_traits<Impl, T, void(P0)>::overload != ill_formed
  303. >::type,
  304. typename enable_if<
  305. call_traits<
  306. Impl,
  307. typename call_traits<Impl, T, void(P0)>::result_type,
  308. void(P1)
  309. >::overload != ill_formed
  310. >::type>
  311. {
  312. ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props);
  313. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  314. (
  315. call_traits<Impl, T, void(P0)>::is_noexcept
  316. &&
  317. call_traits<
  318. Impl,
  319. typename call_traits<Impl, T, void(P0)>::result_type,
  320. void(P1)
  321. >::is_noexcept
  322. ));
  323. typedef typename decay<
  324. typename call_traits<
  325. Impl,
  326. typename call_traits<Impl, T, void(P0)>::result_type,
  327. void(P1)
  328. >::result_type
  329. >::type result_type;
  330. };
  331. template <typename Impl, typename T, typename P0,
  332. typename P1, typename ASIO_ELLIPSIS PN>
  333. struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS),
  334. typename enable_if<
  335. call_traits<Impl, T, void(P0)>::overload != ill_formed
  336. >::type,
  337. typename enable_if<
  338. call_traits<
  339. Impl,
  340. typename call_traits<Impl, T, void(P0)>::result_type,
  341. void(P1, PN ASIO_ELLIPSIS)
  342. >::overload != ill_formed
  343. >::type>
  344. {
  345. ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props);
  346. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  347. (
  348. call_traits<Impl, T, void(P0)>::is_noexcept
  349. &&
  350. call_traits<
  351. Impl,
  352. typename call_traits<Impl, T, void(P0)>::result_type,
  353. void(P1, PN ASIO_ELLIPSIS)
  354. >::is_noexcept
  355. ));
  356. typedef typename decay<
  357. typename call_traits<
  358. Impl,
  359. typename call_traits<Impl, T, void(P0)>::result_type,
  360. void(P1, PN ASIO_ELLIPSIS)
  361. >::result_type
  362. >::type result_type;
  363. };
  364. struct impl
  365. {
  366. template <typename T>
  367. struct proxy
  368. {
  369. #if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \
  370. && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  371. struct type
  372. {
  373. template <typename P>
  374. auto require(ASIO_MOVE_ARG(P) p)
  375. noexcept(
  376. noexcept(
  377. declval<typename conditional<true, T, P>::type>().require(
  378. ASIO_MOVE_CAST(P)(p))
  379. )
  380. )
  381. -> decltype(
  382. declval<typename conditional<true, T, P>::type>().require(
  383. ASIO_MOVE_CAST(P)(p))
  384. );
  385. template <typename P>
  386. auto prefer(ASIO_MOVE_ARG(P) p)
  387. noexcept(
  388. noexcept(
  389. declval<typename conditional<true, T, P>::type>().prefer(
  390. ASIO_MOVE_CAST(P)(p))
  391. )
  392. )
  393. -> decltype(
  394. declval<typename conditional<true, T, P>::type>().prefer(
  395. ASIO_MOVE_CAST(P)(p))
  396. );
  397. };
  398. #else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  399. // && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  400. typedef T type;
  401. #endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
  402. // && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
  403. };
  404. template <typename T, typename Property>
  405. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  406. call_traits<impl, T, void(Property)>::overload == identity,
  407. typename call_traits<impl, T, void(Property)>::result_type
  408. >::type
  409. operator()(
  410. ASIO_MOVE_ARG(T) t,
  411. ASIO_MOVE_ARG(Property)) const
  412. ASIO_NOEXCEPT_IF((
  413. call_traits<impl, T, void(Property)>::is_noexcept))
  414. {
  415. return ASIO_MOVE_CAST(T)(t);
  416. }
  417. template <typename T, typename Property>
  418. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  419. call_traits<impl, T, void(Property)>::overload == call_require_member,
  420. typename call_traits<impl, T, void(Property)>::result_type
  421. >::type
  422. operator()(
  423. ASIO_MOVE_ARG(T) t,
  424. ASIO_MOVE_ARG(Property) p) const
  425. ASIO_NOEXCEPT_IF((
  426. call_traits<impl, T, void(Property)>::is_noexcept))
  427. {
  428. return ASIO_MOVE_CAST(T)(t).require(
  429. ASIO_MOVE_CAST(Property)(p));
  430. }
  431. template <typename T, typename Property>
  432. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  433. call_traits<impl, T, void(Property)>::overload == call_require_free,
  434. typename call_traits<impl, T, void(Property)>::result_type
  435. >::type
  436. operator()(
  437. ASIO_MOVE_ARG(T) t,
  438. ASIO_MOVE_ARG(Property) p) const
  439. ASIO_NOEXCEPT_IF((
  440. call_traits<impl, T, void(Property)>::is_noexcept))
  441. {
  442. return require(
  443. ASIO_MOVE_CAST(T)(t),
  444. ASIO_MOVE_CAST(Property)(p));
  445. }
  446. template <typename T, typename Property>
  447. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  448. call_traits<impl, T, void(Property)>::overload == call_prefer_member,
  449. typename call_traits<impl, T, void(Property)>::result_type
  450. >::type
  451. operator()(
  452. ASIO_MOVE_ARG(T) t,
  453. ASIO_MOVE_ARG(Property) p) const
  454. ASIO_NOEXCEPT_IF((
  455. call_traits<impl, T, void(Property)>::is_noexcept))
  456. {
  457. return ASIO_MOVE_CAST(T)(t).prefer(
  458. ASIO_MOVE_CAST(Property)(p));
  459. }
  460. template <typename T, typename Property>
  461. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  462. call_traits<impl, T, void(Property)>::overload == call_prefer_free,
  463. typename call_traits<impl, T, void(Property)>::result_type
  464. >::type
  465. operator()(
  466. ASIO_MOVE_ARG(T) t,
  467. ASIO_MOVE_ARG(Property) p) const
  468. ASIO_NOEXCEPT_IF((
  469. call_traits<impl, T, void(Property)>::is_noexcept))
  470. {
  471. return prefer(
  472. ASIO_MOVE_CAST(T)(t),
  473. ASIO_MOVE_CAST(Property)(p));
  474. }
  475. template <typename T, typename P0, typename P1>
  476. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  477. call_traits<impl, T, void(P0, P1)>::overload == two_props,
  478. typename call_traits<impl, T, void(P0, P1)>::result_type
  479. >::type
  480. operator()(
  481. ASIO_MOVE_ARG(T) t,
  482. ASIO_MOVE_ARG(P0) p0,
  483. ASIO_MOVE_ARG(P1) p1) const
  484. ASIO_NOEXCEPT_IF((
  485. call_traits<impl, T, void(P0, P1)>::is_noexcept))
  486. {
  487. return (*this)(
  488. (*this)(
  489. ASIO_MOVE_CAST(T)(t),
  490. ASIO_MOVE_CAST(P0)(p0)),
  491. ASIO_MOVE_CAST(P1)(p1));
  492. }
  493. template <typename T, typename P0, typename P1,
  494. typename ASIO_ELLIPSIS PN>
  495. ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<
  496. call_traits<impl, T,
  497. void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,
  498. typename call_traits<impl, T,
  499. void(P0, P1, PN ASIO_ELLIPSIS)>::result_type
  500. >::type
  501. operator()(
  502. ASIO_MOVE_ARG(T) t,
  503. ASIO_MOVE_ARG(P0) p0,
  504. ASIO_MOVE_ARG(P1) p1,
  505. ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const
  506. ASIO_NOEXCEPT_IF((
  507. call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))
  508. {
  509. return (*this)(
  510. (*this)(
  511. ASIO_MOVE_CAST(T)(t),
  512. ASIO_MOVE_CAST(P0)(p0)),
  513. ASIO_MOVE_CAST(P1)(p1),
  514. ASIO_MOVE_CAST(PN)(pn) ASIO_ELLIPSIS);
  515. }
  516. };
  517. template <typename T = impl>
  518. struct static_instance
  519. {
  520. static const T instance;
  521. };
  522. template <typename T>
  523. const T static_instance<T>::instance = {};
  524. } // namespace asio_prefer_fn
  525. namespace asio {
  526. namespace {
  527. static ASIO_CONSTEXPR const asio_prefer_fn::impl&
  528. prefer = asio_prefer_fn::static_instance<>::instance;
  529. } // namespace
  530. typedef asio_prefer_fn::impl prefer_t;
  531. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  532. template <typename T, typename... Properties>
  533. struct can_prefer :
  534. integral_constant<bool,
  535. asio_prefer_fn::call_traits<
  536. prefer_t, T, void(Properties...)>::overload
  537. != asio_prefer_fn::ill_formed>
  538. {
  539. };
  540. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  541. template <typename T, typename P0 = void,
  542. typename P1 = void, typename P2 = void>
  543. struct can_prefer :
  544. integral_constant<bool,
  545. asio_prefer_fn::call_traits<
  546. prefer_t, T, void(P0, P1, P2)>::overload
  547. != asio_prefer_fn::ill_formed>
  548. {
  549. };
  550. template <typename T, typename P0, typename P1>
  551. struct can_prefer<T, P0, P1> :
  552. integral_constant<bool,
  553. asio_prefer_fn::call_traits<
  554. prefer_t, T, void(P0, P1)>::overload
  555. != asio_prefer_fn::ill_formed>
  556. {
  557. };
  558. template <typename T, typename P0>
  559. struct can_prefer<T, P0> :
  560. integral_constant<bool,
  561. asio_prefer_fn::call_traits<
  562. prefer_t, T, void(P0)>::overload
  563. != asio_prefer_fn::ill_formed>
  564. {
  565. };
  566. template <typename T>
  567. struct can_prefer<T> :
  568. false_type
  569. {
  570. };
  571. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  572. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  573. template <typename T, typename ASIO_ELLIPSIS Properties>
  574. constexpr bool can_prefer_v
  575. = can_prefer<T, Properties ASIO_ELLIPSIS>::value;
  576. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  577. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  578. template <typename T, typename... Properties>
  579. struct is_nothrow_prefer :
  580. integral_constant<bool,
  581. asio_prefer_fn::call_traits<
  582. prefer_t, T, void(Properties...)>::is_noexcept>
  583. {
  584. };
  585. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  586. template <typename T, typename P0 = void,
  587. typename P1 = void, typename P2 = void>
  588. struct is_nothrow_prefer :
  589. integral_constant<bool,
  590. asio_prefer_fn::call_traits<
  591. prefer_t, T, void(P0, P1, P2)>::is_noexcept>
  592. {
  593. };
  594. template <typename T, typename P0, typename P1>
  595. struct is_nothrow_prefer<T, P0, P1> :
  596. integral_constant<bool,
  597. asio_prefer_fn::call_traits<
  598. prefer_t, T, void(P0, P1)>::is_noexcept>
  599. {
  600. };
  601. template <typename T, typename P0>
  602. struct is_nothrow_prefer<T, P0> :
  603. integral_constant<bool,
  604. asio_prefer_fn::call_traits<
  605. prefer_t, T, void(P0)>::is_noexcept>
  606. {
  607. };
  608. template <typename T>
  609. struct is_nothrow_prefer<T> :
  610. false_type
  611. {
  612. };
  613. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  614. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  615. template <typename T, typename ASIO_ELLIPSIS Properties>
  616. constexpr bool is_nothrow_prefer_v
  617. = is_nothrow_prefer<T, Properties ASIO_ELLIPSIS>::value;
  618. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  619. #if defined(ASIO_HAS_VARIADIC_TEMPLATES)
  620. template <typename T, typename... Properties>
  621. struct prefer_result
  622. {
  623. typedef typename asio_prefer_fn::call_traits<
  624. prefer_t, T, void(Properties...)>::result_type type;
  625. };
  626. #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  627. template <typename T, typename P0 = void,
  628. typename P1 = void, typename P2 = void>
  629. struct prefer_result
  630. {
  631. typedef typename asio_prefer_fn::call_traits<
  632. prefer_t, T, void(P0, P1, P2)>::result_type type;
  633. };
  634. template <typename T, typename P0, typename P1>
  635. struct prefer_result<T, P0, P1>
  636. {
  637. typedef typename asio_prefer_fn::call_traits<
  638. prefer_t, T, void(P0, P1)>::result_type type;
  639. };
  640. template <typename T, typename P0>
  641. struct prefer_result<T, P0>
  642. {
  643. typedef typename asio_prefer_fn::call_traits<
  644. prefer_t, T, void(P0)>::result_type type;
  645. };
  646. template <typename T>
  647. struct prefer_result<T>
  648. {
  649. };
  650. #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)
  651. } // namespace asio
  652. #endif // defined(GENERATING_DOCUMENTATION)
  653. #include "asio/detail/pop_options.hpp"
  654. #endif // ASIO_PREFER_HPP