relationship.hpp 21 KB

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