relationship.hpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866
  1. //
  2. // execution/relationship.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_EXECUTION_RELATIONSHIP_HPP
  11. #define ASIO_EXECUTION_RELATIONSHIP_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/execution/executor.hpp"
  18. #include "asio/execution/scheduler.hpp"
  19. #include "asio/execution/sender.hpp"
  20. #include "asio/is_applicable_property.hpp"
  21. #include "asio/query.hpp"
  22. #include "asio/traits/query_free.hpp"
  23. #include "asio/traits/query_member.hpp"
  24. #include "asio/traits/query_static_constexpr_member.hpp"
  25. #include "asio/traits/static_query.hpp"
  26. #include "asio/traits/static_require.hpp"
  27. #include "asio/detail/push_options.hpp"
  28. namespace asio {
  29. #if defined(GENERATING_DOCUMENTATION)
  30. namespace execution {
  31. /// A property to describe whether submitted tasks represent continuations of
  32. /// the calling context.
  33. struct relationship_t
  34. {
  35. /// The relationship_t property applies to executors, senders, and schedulers.
  36. template <typename T>
  37. static constexpr bool is_applicable_property_v =
  38. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  39. /// The top-level relationship_t property cannot be required.
  40. static constexpr bool is_requirable = false;
  41. /// The top-level relationship_t property cannot be preferred.
  42. static constexpr bool is_preferable = false;
  43. /// The type returned by queries against an @c any_executor.
  44. typedef relationship_t polymorphic_query_result_type;
  45. /// A sub-property that indicates that the executor does not represent a
  46. /// continuation of the calling context.
  47. struct fork_t
  48. {
  49. /// The relationship_t::fork_t property applies to executors, senders, and
  50. /// schedulers.
  51. template <typename T>
  52. static constexpr bool is_applicable_property_v =
  53. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  54. /// The relationship_t::fork_t property can be required.
  55. static constexpr bool is_requirable = true;
  56. /// The relationship_t::fork_t property can be preferred.
  57. static constexpr bool is_preferable = true;
  58. /// The type returned by queries against an @c any_executor.
  59. typedef relationship_t polymorphic_query_result_type;
  60. /// Default constructor.
  61. constexpr fork_t();
  62. /// Get the value associated with a property object.
  63. /**
  64. * @returns fork_t();
  65. */
  66. static constexpr relationship_t value();
  67. };
  68. /// A sub-property that indicates that the executor represents a continuation
  69. /// of the calling context.
  70. struct continuation_t
  71. {
  72. /// The relationship_t::continuation_t property applies to executors,
  73. /// senders, and schedulers.
  74. template <typename T>
  75. static constexpr bool is_applicable_property_v =
  76. is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;
  77. /// The relationship_t::continuation_t property can be required.
  78. static constexpr bool is_requirable = true;
  79. /// The relationship_t::continuation_t property can be preferred.
  80. static constexpr bool is_preferable = true;
  81. /// The type returned by queries against an @c any_executor.
  82. typedef relationship_t polymorphic_query_result_type;
  83. /// Default constructor.
  84. constexpr continuation_t();
  85. /// Get the value associated with a property object.
  86. /**
  87. * @returns continuation_t();
  88. */
  89. static constexpr relationship_t value();
  90. };
  91. /// A special value used for accessing the relationship_t::fork_t property.
  92. static constexpr fork_t fork;
  93. /// A special value used for accessing the relationship_t::continuation_t
  94. /// property.
  95. static constexpr continuation_t continuation;
  96. /// Default constructor.
  97. constexpr relationship_t();
  98. /// Construct from a sub-property value.
  99. constexpr relationship_t(fork_t);
  100. /// Construct from a sub-property value.
  101. constexpr relationship_t(continuation_t);
  102. /// Compare property values for equality.
  103. friend constexpr bool operator==(
  104. const relationship_t& a, const relationship_t& b) noexcept;
  105. /// Compare property values for inequality.
  106. friend constexpr bool operator!=(
  107. const relationship_t& a, const relationship_t& b) noexcept;
  108. };
  109. /// A special value used for accessing the relationship_t property.
  110. constexpr relationship_t relationship;
  111. } // namespace execution
  112. #else // defined(GENERATING_DOCUMENTATION)
  113. namespace execution {
  114. namespace detail {
  115. namespace relationship {
  116. template <int I> struct fork_t;
  117. template <int I> struct continuation_t;
  118. } // namespace relationship
  119. template <int I = 0>
  120. struct relationship_t
  121. {
  122. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  123. template <typename T>
  124. ASIO_STATIC_CONSTEXPR(bool,
  125. is_applicable_property_v = (
  126. is_executor<T>::value
  127. || conditional<
  128. is_executor<T>::value,
  129. false_type,
  130. is_sender<T>
  131. >::type::value
  132. || conditional<
  133. is_executor<T>::value,
  134. false_type,
  135. is_scheduler<T>
  136. >::type::value));
  137. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  138. ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);
  139. ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);
  140. typedef relationship_t polymorphic_query_result_type;
  141. typedef detail::relationship::fork_t<I> fork_t;
  142. typedef detail::relationship::continuation_t<I> continuation_t;
  143. ASIO_CONSTEXPR relationship_t()
  144. : value_(-1)
  145. {
  146. }
  147. ASIO_CONSTEXPR relationship_t(fork_t)
  148. : value_(0)
  149. {
  150. }
  151. ASIO_CONSTEXPR relationship_t(continuation_t)
  152. : value_(1)
  153. {
  154. }
  155. template <typename T>
  156. struct proxy
  157. {
  158. #if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  159. struct type
  160. {
  161. template <typename P>
  162. auto query(ASIO_MOVE_ARG(P) p) const
  163. noexcept(
  164. noexcept(
  165. declval<typename conditional<true, T, P>::type>().query(
  166. ASIO_MOVE_CAST(P)(p))
  167. )
  168. )
  169. -> decltype(
  170. declval<typename conditional<true, T, P>::type>().query(
  171. ASIO_MOVE_CAST(P)(p))
  172. );
  173. };
  174. #else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  175. typedef T type;
  176. #endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
  177. };
  178. template <typename T>
  179. struct static_proxy
  180. {
  181. #if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  182. struct type
  183. {
  184. template <typename P>
  185. static constexpr auto query(ASIO_MOVE_ARG(P) p)
  186. noexcept(
  187. noexcept(
  188. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  189. )
  190. )
  191. -> decltype(
  192. conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))
  193. )
  194. {
  195. return T::query(ASIO_MOVE_CAST(P)(p));
  196. }
  197. };
  198. #else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  199. typedef T type;
  200. #endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
  201. };
  202. template <typename T>
  203. struct query_member :
  204. traits::query_member<typename proxy<T>::type, relationship_t> {};
  205. template <typename T>
  206. struct query_static_constexpr_member :
  207. traits::query_static_constexpr_member<
  208. typename static_proxy<T>::type, relationship_t> {};
  209. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  210. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  211. template <typename T>
  212. static ASIO_CONSTEXPR
  213. typename query_static_constexpr_member<T>::result_type
  214. static_query()
  215. ASIO_NOEXCEPT_IF((
  216. query_static_constexpr_member<T>::is_noexcept))
  217. {
  218. return query_static_constexpr_member<T>::value();
  219. }
  220. template <typename T>
  221. static ASIO_CONSTEXPR
  222. typename traits::static_query<T, fork_t>::result_type
  223. static_query(
  224. typename enable_if<
  225. !query_static_constexpr_member<T>::is_valid
  226. >::type* = 0,
  227. typename enable_if<
  228. !query_member<T>::is_valid
  229. >::type* = 0,
  230. typename enable_if<
  231. traits::static_query<T, fork_t>::is_valid
  232. >::type* = 0) ASIO_NOEXCEPT
  233. {
  234. return traits::static_query<T, fork_t>::value();
  235. }
  236. template <typename T>
  237. static ASIO_CONSTEXPR
  238. typename traits::static_query<T, continuation_t>::result_type
  239. static_query(
  240. typename enable_if<
  241. !query_static_constexpr_member<T>::is_valid
  242. >::type* = 0,
  243. typename enable_if<
  244. !query_member<T>::is_valid
  245. >::type* = 0,
  246. typename enable_if<
  247. !traits::static_query<T, fork_t>::is_valid
  248. >::type* = 0,
  249. typename enable_if<
  250. traits::static_query<T, continuation_t>::is_valid
  251. >::type* = 0) ASIO_NOEXCEPT
  252. {
  253. return traits::static_query<T, continuation_t>::value();
  254. }
  255. template <typename E,
  256. typename T = decltype(relationship_t::static_query<E>())>
  257. static ASIO_CONSTEXPR const T static_query_v
  258. = relationship_t::static_query<E>();
  259. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  260. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  261. friend ASIO_CONSTEXPR bool operator==(
  262. const relationship_t& a, const relationship_t& b)
  263. {
  264. return a.value_ == b.value_;
  265. }
  266. friend ASIO_CONSTEXPR bool operator!=(
  267. const relationship_t& a, const relationship_t& b)
  268. {
  269. return a.value_ != b.value_;
  270. }
  271. struct convertible_from_relationship_t
  272. {
  273. ASIO_CONSTEXPR convertible_from_relationship_t(relationship_t)
  274. {
  275. }
  276. };
  277. template <typename Executor>
  278. friend ASIO_CONSTEXPR relationship_t query(
  279. const Executor& ex, convertible_from_relationship_t,
  280. typename enable_if<
  281. can_query<const Executor&, fork_t>::value
  282. >::type* = 0)
  283. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  284. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.
  285. ASIO_NOEXCEPT_IF((
  286. is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value))
  287. #else // defined(ASIO_MSVC)
  288. ASIO_NOEXCEPT_IF((
  289. is_nothrow_query<const Executor&, fork_t>::value))
  290. #endif // defined(ASIO_MSVC)
  291. #endif // !defined(__clang__)
  292. {
  293. return asio::query(ex, fork_t());
  294. }
  295. template <typename Executor>
  296. friend ASIO_CONSTEXPR relationship_t query(
  297. const Executor& ex, convertible_from_relationship_t,
  298. typename enable_if<
  299. !can_query<const Executor&, fork_t>::value
  300. >::type* = 0,
  301. typename enable_if<
  302. can_query<const Executor&, continuation_t>::value
  303. >::type* = 0)
  304. #if !defined(__clang__) // Clang crashes if noexcept is used here.
  305. #if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.
  306. ASIO_NOEXCEPT_IF((
  307. is_nothrow_query<const Executor&,
  308. relationship_t<>::continuation_t>::value))
  309. #else // defined(ASIO_MSVC)
  310. ASIO_NOEXCEPT_IF((
  311. is_nothrow_query<const Executor&, continuation_t>::value))
  312. #endif // defined(ASIO_MSVC)
  313. #endif // !defined(__clang__)
  314. {
  315. return asio::query(ex, continuation_t());
  316. }
  317. ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(fork_t, fork);
  318. ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(continuation_t, continuation);
  319. #if !defined(ASIO_HAS_CONSTEXPR)
  320. static const relationship_t instance;
  321. #endif // !defined(ASIO_HAS_CONSTEXPR)
  322. private:
  323. int value_;
  324. };
  325. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  326. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  327. template <int I> template <typename E, typename T>
  328. const T relationship_t<I>::static_query_v;
  329. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  330. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  331. #if !defined(ASIO_HAS_CONSTEXPR)
  332. template <int I>
  333. const relationship_t<I> relationship_t<I>::instance;
  334. #endif
  335. template <int I>
  336. const typename relationship_t<I>::fork_t
  337. relationship_t<I>::fork;
  338. template <int I>
  339. const typename relationship_t<I>::continuation_t
  340. relationship_t<I>::continuation;
  341. namespace relationship {
  342. template <int I = 0>
  343. struct fork_t
  344. {
  345. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  346. template <typename T>
  347. ASIO_STATIC_CONSTEXPR(bool,
  348. is_applicable_property_v = (
  349. is_executor<T>::value
  350. || conditional<
  351. is_executor<T>::value,
  352. false_type,
  353. is_sender<T>
  354. >::type::value
  355. || conditional<
  356. is_executor<T>::value,
  357. false_type,
  358. is_scheduler<T>
  359. >::type::value));
  360. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  361. ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  362. ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  363. typedef relationship_t<I> polymorphic_query_result_type;
  364. ASIO_CONSTEXPR fork_t()
  365. {
  366. }
  367. template <typename T>
  368. struct query_member :
  369. traits::query_member<
  370. typename relationship_t<I>::template proxy<T>::type, fork_t> {};
  371. template <typename T>
  372. struct query_static_constexpr_member :
  373. traits::query_static_constexpr_member<
  374. typename relationship_t<I>::template static_proxy<T>::type, fork_t> {};
  375. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  376. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  377. template <typename T>
  378. static ASIO_CONSTEXPR
  379. typename query_static_constexpr_member<T>::result_type
  380. static_query()
  381. ASIO_NOEXCEPT_IF((
  382. query_static_constexpr_member<T>::is_noexcept))
  383. {
  384. return query_static_constexpr_member<T>::value();
  385. }
  386. template <typename T>
  387. static ASIO_CONSTEXPR fork_t static_query(
  388. typename enable_if<
  389. !query_static_constexpr_member<T>::is_valid
  390. >::type* = 0,
  391. typename enable_if<
  392. !query_member<T>::is_valid
  393. >::type* = 0,
  394. typename enable_if<
  395. !traits::query_free<T, fork_t>::is_valid
  396. >::type* = 0,
  397. typename enable_if<
  398. !can_query<T, continuation_t<I> >::value
  399. >::type* = 0) ASIO_NOEXCEPT
  400. {
  401. return fork_t();
  402. }
  403. template <typename E, typename T = decltype(fork_t::static_query<E>())>
  404. static ASIO_CONSTEXPR const T static_query_v
  405. = fork_t::static_query<E>();
  406. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  407. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  408. static ASIO_CONSTEXPR relationship_t<I> value()
  409. {
  410. return fork_t();
  411. }
  412. friend ASIO_CONSTEXPR bool operator==(
  413. const fork_t&, const fork_t&)
  414. {
  415. return true;
  416. }
  417. friend ASIO_CONSTEXPR bool operator!=(
  418. const fork_t&, const fork_t&)
  419. {
  420. return false;
  421. }
  422. };
  423. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  424. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  425. template <int I> template <typename E, typename T>
  426. const T fork_t<I>::static_query_v;
  427. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  428. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  429. template <int I = 0>
  430. struct continuation_t
  431. {
  432. #if defined(ASIO_HAS_VARIABLE_TEMPLATES)
  433. template <typename T>
  434. ASIO_STATIC_CONSTEXPR(bool,
  435. is_applicable_property_v = (
  436. is_executor<T>::value
  437. || conditional<
  438. is_executor<T>::value,
  439. false_type,
  440. is_sender<T>
  441. >::type::value
  442. || conditional<
  443. is_executor<T>::value,
  444. false_type,
  445. is_scheduler<T>
  446. >::type::value));
  447. #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)
  448. ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);
  449. ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);
  450. typedef relationship_t<I> polymorphic_query_result_type;
  451. ASIO_CONSTEXPR continuation_t()
  452. {
  453. }
  454. template <typename T>
  455. struct query_member :
  456. traits::query_member<
  457. typename relationship_t<I>::template proxy<T>::type, continuation_t> {};
  458. template <typename T>
  459. struct query_static_constexpr_member :
  460. traits::query_static_constexpr_member<
  461. typename relationship_t<I>::template static_proxy<T>::type,
  462. continuation_t> {};
  463. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  464. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  465. template <typename T>
  466. static ASIO_CONSTEXPR
  467. typename query_static_constexpr_member<T>::result_type
  468. static_query()
  469. ASIO_NOEXCEPT_IF((
  470. query_static_constexpr_member<T>::is_noexcept))
  471. {
  472. return query_static_constexpr_member<T>::value();
  473. }
  474. template <typename E,
  475. typename T = decltype(continuation_t::static_query<E>())>
  476. static ASIO_CONSTEXPR const T static_query_v
  477. = continuation_t::static_query<E>();
  478. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  479. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  480. static ASIO_CONSTEXPR relationship_t<I> value()
  481. {
  482. return continuation_t();
  483. }
  484. friend ASIO_CONSTEXPR bool operator==(
  485. const continuation_t&, const continuation_t&)
  486. {
  487. return true;
  488. }
  489. friend ASIO_CONSTEXPR bool operator!=(
  490. const continuation_t&, const continuation_t&)
  491. {
  492. return false;
  493. }
  494. };
  495. #if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  496. && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  497. template <int I> template <typename E, typename T>
  498. const T continuation_t<I>::static_query_v;
  499. #endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  500. // && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  501. } // namespace relationship
  502. } // namespace detail
  503. typedef detail::relationship_t<> relationship_t;
  504. #if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  505. constexpr relationship_t relationship;
  506. #else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)
  507. namespace { static const relationship_t&
  508. relationship = relationship_t::instance; }
  509. #endif
  510. } // namespace execution
  511. #if !defined(ASIO_HAS_VARIABLE_TEMPLATES)
  512. template <typename T>
  513. struct is_applicable_property<T, execution::relationship_t>
  514. : integral_constant<bool,
  515. execution::is_executor<T>::value
  516. || conditional<
  517. execution::is_executor<T>::value,
  518. false_type,
  519. execution::is_sender<T>
  520. >::type::value
  521. || conditional<
  522. execution::is_executor<T>::value,
  523. false_type,
  524. execution::is_scheduler<T>
  525. >::type::value>
  526. {
  527. };
  528. template <typename T>
  529. struct is_applicable_property<T, execution::relationship_t::fork_t>
  530. : integral_constant<bool,
  531. execution::is_executor<T>::value
  532. || conditional<
  533. execution::is_executor<T>::value,
  534. false_type,
  535. execution::is_sender<T>
  536. >::type::value
  537. || conditional<
  538. execution::is_executor<T>::value,
  539. false_type,
  540. execution::is_scheduler<T>
  541. >::type::value>
  542. {
  543. };
  544. template <typename T>
  545. struct is_applicable_property<T, execution::relationship_t::continuation_t>
  546. : integral_constant<bool,
  547. execution::is_executor<T>::value
  548. || conditional<
  549. execution::is_executor<T>::value,
  550. false_type,
  551. execution::is_sender<T>
  552. >::type::value
  553. || conditional<
  554. execution::is_executor<T>::value,
  555. false_type,
  556. execution::is_scheduler<T>
  557. >::type::value>
  558. {
  559. };
  560. #endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)
  561. namespace traits {
  562. #if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  563. template <typename T>
  564. struct query_free_default<T, execution::relationship_t,
  565. typename enable_if<
  566. can_query<T, execution::relationship_t::fork_t>::value
  567. >::type>
  568. {
  569. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  570. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  571. (is_nothrow_query<T, execution::relationship_t::fork_t>::value));
  572. typedef execution::relationship_t result_type;
  573. };
  574. template <typename T>
  575. struct query_free_default<T, execution::relationship_t,
  576. typename enable_if<
  577. !can_query<T, execution::relationship_t::fork_t>::value
  578. && can_query<T, execution::relationship_t::continuation_t>::value
  579. >::type>
  580. {
  581. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  582. ASIO_STATIC_CONSTEXPR(bool, is_noexcept =
  583. (is_nothrow_query<T, execution::relationship_t::continuation_t>::value));
  584. typedef execution::relationship_t result_type;
  585. };
  586. #endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)
  587. #if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \
  588. || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  589. template <typename T>
  590. struct static_query<T, execution::relationship_t,
  591. typename enable_if<
  592. execution::detail::relationship_t<0>::
  593. query_static_constexpr_member<T>::is_valid
  594. >::type>
  595. {
  596. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  597. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  598. typedef typename execution::detail::relationship_t<0>::
  599. query_static_constexpr_member<T>::result_type result_type;
  600. static ASIO_CONSTEXPR result_type value()
  601. {
  602. return execution::detail::relationship_t<0>::
  603. query_static_constexpr_member<T>::value();
  604. }
  605. };
  606. template <typename T>
  607. struct static_query<T, execution::relationship_t,
  608. typename enable_if<
  609. !execution::detail::relationship_t<0>::
  610. query_static_constexpr_member<T>::is_valid
  611. && !execution::detail::relationship_t<0>::
  612. query_member<T>::is_valid
  613. && traits::static_query<T,
  614. execution::relationship_t::fork_t>::is_valid
  615. >::type>
  616. {
  617. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  618. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  619. typedef typename traits::static_query<T,
  620. execution::relationship_t::fork_t>::result_type result_type;
  621. static ASIO_CONSTEXPR result_type value()
  622. {
  623. return traits::static_query<T,
  624. execution::relationship_t::fork_t>::value();
  625. }
  626. };
  627. template <typename T>
  628. struct static_query<T, execution::relationship_t,
  629. typename enable_if<
  630. !execution::detail::relationship_t<0>::
  631. query_static_constexpr_member<T>::is_valid
  632. && !execution::detail::relationship_t<0>::
  633. query_member<T>::is_valid
  634. && !traits::static_query<T,
  635. execution::relationship_t::fork_t>::is_valid
  636. && traits::static_query<T,
  637. execution::relationship_t::continuation_t>::is_valid
  638. >::type>
  639. {
  640. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  641. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  642. typedef typename traits::static_query<T,
  643. execution::relationship_t::continuation_t>::result_type result_type;
  644. static ASIO_CONSTEXPR result_type value()
  645. {
  646. return traits::static_query<T,
  647. execution::relationship_t::continuation_t>::value();
  648. }
  649. };
  650. template <typename T>
  651. struct static_query<T, execution::relationship_t::fork_t,
  652. typename enable_if<
  653. execution::detail::relationship::fork_t<0>::
  654. query_static_constexpr_member<T>::is_valid
  655. >::type>
  656. {
  657. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  658. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  659. typedef typename execution::detail::relationship::fork_t<0>::
  660. query_static_constexpr_member<T>::result_type result_type;
  661. static ASIO_CONSTEXPR result_type value()
  662. {
  663. return execution::detail::relationship::fork_t<0>::
  664. query_static_constexpr_member<T>::value();
  665. }
  666. };
  667. template <typename T>
  668. struct static_query<T, execution::relationship_t::fork_t,
  669. typename enable_if<
  670. !execution::detail::relationship::fork_t<0>::
  671. query_static_constexpr_member<T>::is_valid
  672. && !execution::detail::relationship::fork_t<0>::
  673. query_member<T>::is_valid
  674. && !traits::query_free<T,
  675. execution::relationship_t::fork_t>::is_valid
  676. && !can_query<T, execution::relationship_t::continuation_t>::value
  677. >::type>
  678. {
  679. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  680. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  681. typedef execution::relationship_t::fork_t result_type;
  682. static ASIO_CONSTEXPR result_type value()
  683. {
  684. return result_type();
  685. }
  686. };
  687. template <typename T>
  688. struct static_query<T, execution::relationship_t::continuation_t,
  689. typename enable_if<
  690. execution::detail::relationship::continuation_t<0>::
  691. query_static_constexpr_member<T>::is_valid
  692. >::type>
  693. {
  694. ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
  695. ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);
  696. typedef typename execution::detail::relationship::continuation_t<0>::
  697. query_static_constexpr_member<T>::result_type result_type;
  698. static ASIO_CONSTEXPR result_type value()
  699. {
  700. return execution::detail::relationship::continuation_t<0>::
  701. query_static_constexpr_member<T>::value();
  702. }
  703. };
  704. #endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)
  705. // || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)
  706. #if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  707. template <typename T>
  708. struct static_require<T, execution::relationship_t::fork_t,
  709. typename enable_if<
  710. static_query<T, execution::relationship_t::fork_t>::is_valid
  711. >::type>
  712. {
  713. ASIO_STATIC_CONSTEXPR(bool, is_valid =
  714. (is_same<typename static_query<T,
  715. execution::relationship_t::fork_t>::result_type,
  716. execution::relationship_t::fork_t>::value));
  717. };
  718. template <typename T>
  719. struct static_require<T, execution::relationship_t::continuation_t,
  720. typename enable_if<
  721. static_query<T, execution::relationship_t::continuation_t>::is_valid
  722. >::type>
  723. {
  724. ASIO_STATIC_CONSTEXPR(bool, is_valid =
  725. (is_same<typename static_query<T,
  726. execution::relationship_t::continuation_t>::result_type,
  727. execution::relationship_t::continuation_t>::value));
  728. };
  729. #endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)
  730. } // namespace traits
  731. #endif // defined(GENERATING_DOCUMENTATION)
  732. } // namespace asio
  733. #include "asio/detail/pop_options.hpp"
  734. #endif // ASIO_EXECUTION_RELATIONSHIP_HPP