mapping.hpp 28 KB

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