deferred.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. //
  2. // deferred.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 BOOST_ASIO_DEFERRED_HPP
  11. #define BOOST_ASIO_DEFERRED_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <tuple>
  17. #include <boost/asio/associator.hpp>
  18. #include <boost/asio/async_result.hpp>
  19. #include <boost/asio/detail/type_traits.hpp>
  20. #include <boost/asio/detail/utility.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. /// Trait for detecting objects that are usable as deferred operations.
  25. template <typename T>
  26. struct is_deferred : false_type
  27. {
  28. };
  29. /// Helper type to wrap multiple completion signatures.
  30. template <typename... Signatures>
  31. struct deferred_signatures
  32. {
  33. };
  34. namespace detail {
  35. // Helper trait for getting the completion signatures of the tail in a sequence
  36. // when invoked with the specified arguments.
  37. template <typename Tail, typename... Signatures>
  38. struct deferred_sequence_signatures;
  39. template <typename Tail, typename R, typename... Args, typename... Signatures>
  40. struct deferred_sequence_signatures<Tail, R(Args...), Signatures...>
  41. : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))>
  42. {
  43. static_assert(
  44. !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,
  45. "deferred functions must produce a deferred return type");
  46. };
  47. // Completion handler for the head component of a deferred sequence.
  48. template <typename Handler, typename Tail>
  49. class deferred_sequence_handler
  50. {
  51. public:
  52. template <typename H, typename T>
  53. explicit deferred_sequence_handler(H&& handler, T&& tail)
  54. : handler_(static_cast<H&&>(handler)),
  55. tail_(static_cast<T&&>(tail))
  56. {
  57. }
  58. template <typename... Args>
  59. void operator()(Args&&... args)
  60. {
  61. static_cast<Tail&&>(tail_)(
  62. static_cast<Args&&>(args)...)(
  63. static_cast<Handler&&>(handler_));
  64. }
  65. //private:
  66. Handler handler_;
  67. Tail tail_;
  68. };
  69. template <typename Head, typename Tail, typename... Signatures>
  70. class deferred_sequence_base
  71. {
  72. private:
  73. struct initiate
  74. {
  75. template <typename Handler>
  76. void operator()(Handler&& handler, Head head, Tail&& tail)
  77. {
  78. static_cast<Head&&>(head)(
  79. deferred_sequence_handler<decay_t<Handler>, decay_t<Tail>>(
  80. static_cast<Handler&&>(handler), static_cast<Tail&&>(tail)));
  81. }
  82. };
  83. Head head_;
  84. Tail tail_;
  85. public:
  86. template <typename H, typename T>
  87. constexpr explicit deferred_sequence_base(H&& head, T&& tail)
  88. : head_(static_cast<H&&>(head)),
  89. tail_(static_cast<T&&>(tail))
  90. {
  91. }
  92. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  93. auto operator()(CompletionToken&& token) &&
  94. -> decltype(
  95. async_initiate<CompletionToken, Signatures...>(
  96. initiate(), token, static_cast<Head&&>(this->head_),
  97. static_cast<Tail&&>(this->tail_)))
  98. {
  99. return async_initiate<CompletionToken, Signatures...>(initiate(),
  100. token, static_cast<Head&&>(head_), static_cast<Tail&&>(tail_));
  101. }
  102. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  103. auto operator()(CompletionToken&& token) const &
  104. -> decltype(
  105. async_initiate<CompletionToken, Signatures...>(
  106. initiate(), token, this->head_, this->tail_))
  107. {
  108. return async_initiate<CompletionToken, Signatures...>(
  109. initiate(), token, head_, tail_);
  110. }
  111. };
  112. // Two-step application of variadic Signatures to determine correct base type.
  113. template <typename Head, typename Tail>
  114. struct deferred_sequence_types
  115. {
  116. template <typename... Signatures>
  117. struct op1
  118. {
  119. typedef deferred_sequence_base<Head, Tail, Signatures...> type;
  120. };
  121. template <typename... Signatures>
  122. struct op2
  123. {
  124. typedef typename deferred_sequence_signatures<Tail, Signatures...>::template
  125. apply<op1>::type::type type;
  126. };
  127. typedef typename completion_signature_of<Head>::template
  128. apply<op2>::type::type base;
  129. };
  130. } // namespace detail
  131. /// Used to represent an empty deferred action.
  132. struct deferred_noop
  133. {
  134. /// No effect.
  135. template <typename... Args>
  136. void operator()(Args&&...) &&
  137. {
  138. }
  139. /// No effect.
  140. template <typename... Args>
  141. void operator()(Args&&...) const &
  142. {
  143. }
  144. };
  145. #if !defined(GENERATING_DOCUMENTATION)
  146. template <>
  147. struct is_deferred<deferred_noop> : true_type
  148. {
  149. };
  150. #endif // !defined(GENERATING_DOCUMENTATION)
  151. /// Tag type to disambiguate deferred constructors.
  152. struct deferred_init_tag {};
  153. /// Wraps a function object so that it may be used as an element in a deferred
  154. /// composition.
  155. template <typename Function>
  156. class deferred_function
  157. {
  158. public:
  159. /// Constructor.
  160. template <typename F>
  161. constexpr explicit deferred_function(deferred_init_tag, F&& function)
  162. : function_(static_cast<F&&>(function))
  163. {
  164. }
  165. //private:
  166. Function function_;
  167. public:
  168. template <typename... Args>
  169. auto operator()(Args&&... args) &&
  170. -> decltype(
  171. static_cast<Function&&>(this->function_)(static_cast<Args&&>(args)...))
  172. {
  173. return static_cast<Function&&>(function_)(static_cast<Args&&>(args)...);
  174. }
  175. template <typename... Args>
  176. auto operator()(Args&&... args) const &
  177. -> decltype(Function(function_)(static_cast<Args&&>(args)...))
  178. {
  179. return Function(function_)(static_cast<Args&&>(args)...);
  180. }
  181. };
  182. #if !defined(GENERATING_DOCUMENTATION)
  183. template <typename Function>
  184. struct is_deferred<deferred_function<Function>> : true_type
  185. {
  186. };
  187. #endif // !defined(GENERATING_DOCUMENTATION)
  188. /// Encapsulates deferred values.
  189. template <typename... Values>
  190. class BOOST_ASIO_NODISCARD deferred_values
  191. {
  192. private:
  193. std::tuple<Values...> values_;
  194. struct initiate
  195. {
  196. template <typename Handler, typename... V>
  197. void operator()(Handler handler, V&&... values)
  198. {
  199. static_cast<Handler&&>(handler)(static_cast<V&&>(values)...);
  200. }
  201. };
  202. template <typename CompletionToken, std::size_t... I>
  203. auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
  204. -> decltype(
  205. async_initiate<CompletionToken, void(Values...)>(initiate(), token,
  206. std::get<I>(static_cast<std::tuple<Values...>&&>(this->values_))...))
  207. {
  208. return async_initiate<CompletionToken, void(Values...)>(initiate(), token,
  209. std::get<I>(static_cast<std::tuple<Values...>&&>(values_))...);
  210. }
  211. template <typename CompletionToken, std::size_t... I>
  212. auto const_invoke_helper(CompletionToken&& token,
  213. detail::index_sequence<I...>)
  214. -> decltype(
  215. async_initiate<CompletionToken, void(Values...)>(
  216. initiate(), token, std::get<I>(values_)...))
  217. {
  218. return async_initiate<CompletionToken, void(Values...)>(
  219. initiate(), token, std::get<I>(values_)...);
  220. }
  221. public:
  222. /// Construct a deferred asynchronous operation from the arguments to an
  223. /// initiation function object.
  224. template <typename... V>
  225. constexpr explicit deferred_values(
  226. deferred_init_tag, V&&... values)
  227. : values_(static_cast<V&&>(values)...)
  228. {
  229. }
  230. /// Initiate the deferred operation using the supplied completion token.
  231. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
  232. auto operator()(CompletionToken&& token) &&
  233. -> decltype(
  234. this->invoke_helper(
  235. static_cast<CompletionToken&&>(token),
  236. detail::index_sequence_for<Values...>()))
  237. {
  238. return this->invoke_helper(
  239. static_cast<CompletionToken&&>(token),
  240. detail::index_sequence_for<Values...>());
  241. }
  242. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
  243. auto operator()(CompletionToken&& token) const &
  244. -> decltype(
  245. this->const_invoke_helper(
  246. static_cast<CompletionToken&&>(token),
  247. detail::index_sequence_for<Values...>()))
  248. {
  249. return this->const_invoke_helper(
  250. static_cast<CompletionToken&&>(token),
  251. detail::index_sequence_for<Values...>());
  252. }
  253. };
  254. #if !defined(GENERATING_DOCUMENTATION)
  255. template <typename... Values>
  256. struct is_deferred<deferred_values<Values...>> : true_type
  257. {
  258. };
  259. #endif // !defined(GENERATING_DOCUMENTATION)
  260. /// Encapsulates a deferred asynchronous operation.
  261. template <typename Signature, typename Initiation, typename... InitArgs>
  262. class BOOST_ASIO_NODISCARD deferred_async_operation
  263. {
  264. private:
  265. typedef decay_t<Initiation> initiation_t;
  266. initiation_t initiation_;
  267. typedef std::tuple<decay_t<InitArgs>...> init_args_t;
  268. init_args_t init_args_;
  269. template <typename CompletionToken, std::size_t... I>
  270. auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
  271. -> decltype(
  272. async_initiate<CompletionToken, Signature>(
  273. static_cast<initiation_t&&>(initiation_), token,
  274. std::get<I>(static_cast<init_args_t&&>(init_args_))...))
  275. {
  276. return async_initiate<CompletionToken, Signature>(
  277. static_cast<initiation_t&&>(initiation_), token,
  278. std::get<I>(static_cast<init_args_t&&>(init_args_))...);
  279. }
  280. template <typename CompletionToken, std::size_t... I>
  281. auto const_invoke_helper(CompletionToken&& token,
  282. detail::index_sequence<I...>) const &
  283. -> decltype(
  284. async_initiate<CompletionToken, Signature>(
  285. initiation_t(initiation_), token, std::get<I>(init_args_)...))
  286. {
  287. return async_initiate<CompletionToken, Signature>(
  288. initiation_t(initiation_), token, std::get<I>(init_args_)...);
  289. }
  290. public:
  291. /// Construct a deferred asynchronous operation from the arguments to an
  292. /// initiation function object.
  293. template <typename I, typename... A>
  294. constexpr explicit deferred_async_operation(
  295. deferred_init_tag, I&& initiation, A&&... init_args)
  296. : initiation_(static_cast<I&&>(initiation)),
  297. init_args_(static_cast<A&&>(init_args)...)
  298. {
  299. }
  300. /// Initiate the asynchronous operation using the supplied completion token.
  301. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
  302. auto operator()(CompletionToken&& token) &&
  303. -> decltype(
  304. this->invoke_helper(
  305. static_cast<CompletionToken&&>(token),
  306. detail::index_sequence_for<InitArgs...>()))
  307. {
  308. return this->invoke_helper(
  309. static_cast<CompletionToken&&>(token),
  310. detail::index_sequence_for<InitArgs...>());
  311. }
  312. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
  313. auto operator()(CompletionToken&& token) const &
  314. -> decltype(
  315. this->const_invoke_helper(
  316. static_cast<CompletionToken&&>(token),
  317. detail::index_sequence_for<InitArgs...>()))
  318. {
  319. return this->const_invoke_helper(
  320. static_cast<CompletionToken&&>(token),
  321. detail::index_sequence_for<InitArgs...>());
  322. }
  323. };
  324. /// Encapsulates a deferred asynchronous operation thas has multiple completion
  325. /// signatures.
  326. template <typename... Signatures, typename Initiation, typename... InitArgs>
  327. class BOOST_ASIO_NODISCARD deferred_async_operation<
  328. deferred_signatures<Signatures...>, Initiation, InitArgs...>
  329. {
  330. private:
  331. typedef decay_t<Initiation> initiation_t;
  332. initiation_t initiation_;
  333. typedef std::tuple<decay_t<InitArgs>...> init_args_t;
  334. init_args_t init_args_;
  335. template <typename CompletionToken, std::size_t... I>
  336. auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
  337. -> decltype(
  338. async_initiate<CompletionToken, Signatures...>(
  339. static_cast<initiation_t&&>(initiation_), token,
  340. std::get<I>(static_cast<init_args_t&&>(init_args_))...))
  341. {
  342. return async_initiate<CompletionToken, Signatures...>(
  343. static_cast<initiation_t&&>(initiation_), token,
  344. std::get<I>(static_cast<init_args_t&&>(init_args_))...);
  345. }
  346. template <typename CompletionToken, std::size_t... I>
  347. auto const_invoke_helper(CompletionToken&& token,
  348. detail::index_sequence<I...>) const &
  349. -> decltype(
  350. async_initiate<CompletionToken, Signatures...>(
  351. initiation_t(initiation_), token, std::get<I>(init_args_)...))
  352. {
  353. return async_initiate<CompletionToken, Signatures...>(
  354. initiation_t(initiation_), token, std::get<I>(init_args_)...);
  355. }
  356. public:
  357. /// Construct a deferred asynchronous operation from the arguments to an
  358. /// initiation function object.
  359. template <typename I, typename... A>
  360. constexpr explicit deferred_async_operation(
  361. deferred_init_tag, I&& initiation, A&&... init_args)
  362. : initiation_(static_cast<I&&>(initiation)),
  363. init_args_(static_cast<A&&>(init_args)...)
  364. {
  365. }
  366. /// Initiate the asynchronous operation using the supplied completion token.
  367. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  368. auto operator()(CompletionToken&& token) &&
  369. -> decltype(
  370. this->invoke_helper(
  371. static_cast<CompletionToken&&>(token),
  372. detail::index_sequence_for<InitArgs...>()))
  373. {
  374. return this->invoke_helper(
  375. static_cast<CompletionToken&&>(token),
  376. detail::index_sequence_for<InitArgs...>());
  377. }
  378. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  379. auto operator()(CompletionToken&& token) const &
  380. -> decltype(
  381. this->const_invoke_helper(
  382. static_cast<CompletionToken&&>(token),
  383. detail::index_sequence_for<InitArgs...>()))
  384. {
  385. return this->const_invoke_helper(
  386. static_cast<CompletionToken&&>(token),
  387. detail::index_sequence_for<InitArgs...>());
  388. }
  389. };
  390. #if !defined(GENERATING_DOCUMENTATION)
  391. template <typename Signature, typename Initiation, typename... InitArgs>
  392. struct is_deferred<
  393. deferred_async_operation<Signature, Initiation, InitArgs...>> : true_type
  394. {
  395. };
  396. #endif // !defined(GENERATING_DOCUMENTATION)
  397. /// Defines a link between two consecutive operations in a sequence.
  398. template <typename Head, typename Tail>
  399. class BOOST_ASIO_NODISCARD deferred_sequence :
  400. public detail::deferred_sequence_types<Head, Tail>::base
  401. {
  402. public:
  403. template <typename H, typename T>
  404. constexpr explicit deferred_sequence(deferred_init_tag, H&& head, T&& tail)
  405. : detail::deferred_sequence_types<Head, Tail>::base(
  406. static_cast<H&&>(head), static_cast<T&&>(tail))
  407. {
  408. }
  409. #if defined(GENERATING_DOCUMENTATION)
  410. template <typename CompletionToken>
  411. auto operator()(CompletionToken&& token) &&;
  412. template <typename CompletionToken>
  413. auto operator()(CompletionToken&& token) const &;
  414. #endif // defined(GENERATING_DOCUMENTATION)
  415. };
  416. #if !defined(GENERATING_DOCUMENTATION)
  417. template <typename Head, typename Tail>
  418. struct is_deferred<deferred_sequence<Head, Tail>> : true_type
  419. {
  420. };
  421. #endif // !defined(GENERATING_DOCUMENTATION)
  422. /// Used to represent a deferred conditional branch.
  423. template <typename OnTrue = deferred_noop, typename OnFalse = deferred_noop>
  424. class BOOST_ASIO_NODISCARD deferred_conditional
  425. {
  426. private:
  427. template <typename T, typename F> friend class deferred_conditional;
  428. // Helper constructor.
  429. template <typename T, typename F>
  430. explicit deferred_conditional(bool b, T&& on_true, F&& on_false)
  431. : on_true_(static_cast<T&&>(on_true)),
  432. on_false_(static_cast<F&&>(on_false)),
  433. bool_(b)
  434. {
  435. }
  436. OnTrue on_true_;
  437. OnFalse on_false_;
  438. bool bool_;
  439. public:
  440. /// Construct a deferred conditional with the value to determine which branch
  441. /// will be executed.
  442. constexpr explicit deferred_conditional(bool b)
  443. : on_true_(),
  444. on_false_(),
  445. bool_(b)
  446. {
  447. }
  448. /// Invoke the conditional branch bsaed on the stored value.
  449. template <typename... Args>
  450. auto operator()(Args&&... args) &&
  451. -> decltype(static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...))
  452. {
  453. if (bool_)
  454. {
  455. return static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...);
  456. }
  457. else
  458. {
  459. return static_cast<OnFalse&&>(on_false_)(static_cast<Args&&>(args)...);
  460. }
  461. }
  462. template <typename... Args>
  463. auto operator()(Args&&... args) const &
  464. -> decltype(on_true_(static_cast<Args&&>(args)...))
  465. {
  466. if (bool_)
  467. {
  468. return on_true_(static_cast<Args&&>(args)...);
  469. }
  470. else
  471. {
  472. return on_false_(static_cast<Args&&>(args)...);
  473. }
  474. }
  475. /// Set the true branch of the conditional.
  476. template <typename T>
  477. deferred_conditional<T, OnFalse> then(T on_true,
  478. constraint_t<
  479. is_deferred<T>::value
  480. >* = 0,
  481. constraint_t<
  482. is_same<
  483. conditional_t<true, OnTrue, T>,
  484. deferred_noop
  485. >::value
  486. >* = 0) &&
  487. {
  488. return deferred_conditional<T, OnFalse>(
  489. bool_, static_cast<T&&>(on_true),
  490. static_cast<OnFalse&&>(on_false_));
  491. }
  492. /// Set the false branch of the conditional.
  493. template <typename T>
  494. deferred_conditional<OnTrue, T> otherwise(T on_false,
  495. constraint_t<
  496. is_deferred<T>::value
  497. >* = 0,
  498. constraint_t<
  499. !is_same<
  500. conditional_t<true, OnTrue, T>,
  501. deferred_noop
  502. >::value
  503. >* = 0,
  504. constraint_t<
  505. is_same<
  506. conditional_t<true, OnFalse, T>,
  507. deferred_noop
  508. >::value
  509. >* = 0) &&
  510. {
  511. return deferred_conditional<OnTrue, T>(
  512. bool_, static_cast<OnTrue&&>(on_true_),
  513. static_cast<T&&>(on_false));
  514. }
  515. };
  516. #if !defined(GENERATING_DOCUMENTATION)
  517. template <typename OnTrue, typename OnFalse>
  518. struct is_deferred<deferred_conditional<OnTrue, OnFalse>> : true_type
  519. {
  520. };
  521. #endif // !defined(GENERATING_DOCUMENTATION)
  522. /// Class used to specify that an asynchronous operation should return a
  523. /// function object to lazily launch the operation.
  524. /**
  525. * The deferred_t class is used to indicate that an asynchronous operation
  526. * should return a function object which is itself an initiation function. A
  527. * deferred_t object may be passed as a completion token to an asynchronous
  528. * operation, typically using the special value @c boost::asio::deferred. For
  529. * example:
  530. *
  531. * @code auto my_deferred_op
  532. * = my_socket.async_read_some(my_buffer,
  533. * boost::asio::deferred); @endcode
  534. *
  535. * The initiating function (async_read_some in the above example) returns a
  536. * function object that will lazily initiate the operation.
  537. */
  538. class deferred_t
  539. {
  540. public:
  541. /// Default constructor.
  542. constexpr deferred_t()
  543. {
  544. }
  545. /// Adapts an executor to add the @c deferred_t completion token as the
  546. /// default.
  547. template <typename InnerExecutor>
  548. struct executor_with_default : InnerExecutor
  549. {
  550. /// Specify @c deferred_t as the default completion token type.
  551. typedef deferred_t default_completion_token_type;
  552. /// Construct the adapted executor from the inner executor type.
  553. template <typename InnerExecutor1>
  554. executor_with_default(const InnerExecutor1& ex,
  555. constraint_t<
  556. conditional_t<
  557. !is_same<InnerExecutor1, executor_with_default>::value,
  558. is_convertible<InnerExecutor1, InnerExecutor>,
  559. false_type
  560. >::value
  561. > = 0) noexcept
  562. : InnerExecutor(ex)
  563. {
  564. }
  565. };
  566. /// Type alias to adapt an I/O object to use @c deferred_t as its
  567. /// default completion token type.
  568. template <typename T>
  569. using as_default_on_t = typename T::template rebind_executor<
  570. executor_with_default<typename T::executor_type>>::other;
  571. /// Function helper to adapt an I/O object to use @c deferred_t as its
  572. /// default completion token type.
  573. template <typename T>
  574. static typename decay_t<T>::template rebind_executor<
  575. executor_with_default<typename decay_t<T>::executor_type>
  576. >::other
  577. as_default_on(T&& object)
  578. {
  579. return typename decay_t<T>::template rebind_executor<
  580. executor_with_default<typename decay_t<T>::executor_type>
  581. >::other(static_cast<T&&>(object));
  582. }
  583. /// Creates a new deferred from a function.
  584. template <typename Function>
  585. constraint_t<
  586. !is_deferred<decay_t<Function>>::value,
  587. deferred_function<decay_t<Function>>
  588. > operator()(Function&& function) const
  589. {
  590. return deferred_function<decay_t<Function>>(
  591. deferred_init_tag{}, static_cast<Function&&>(function));
  592. }
  593. /// Passes through anything that is already deferred.
  594. template <typename T>
  595. constraint_t<
  596. is_deferred<decay_t<T>>::value,
  597. decay_t<T>
  598. > operator()(T&& t) const
  599. {
  600. return static_cast<T&&>(t);
  601. }
  602. /// Returns a deferred operation that returns the provided values.
  603. template <typename... Args>
  604. static constexpr deferred_values<decay_t<Args>...> values(Args&&... args)
  605. {
  606. return deferred_values<decay_t<Args>...>(
  607. deferred_init_tag{}, static_cast<Args&&>(args)...);
  608. }
  609. /// Creates a conditional object for branching deferred operations.
  610. static constexpr deferred_conditional<> when(bool b)
  611. {
  612. return deferred_conditional<>(b);
  613. }
  614. };
  615. /// Pipe operator used to chain deferred operations.
  616. template <typename Head, typename Tail>
  617. inline auto operator|(Head head, Tail&& tail)
  618. -> constraint_t<
  619. is_deferred<Head>::value,
  620. decltype(static_cast<Head&&>(head)(static_cast<Tail&&>(tail)))
  621. >
  622. {
  623. return static_cast<Head&&>(head)(static_cast<Tail&&>(tail));
  624. }
  625. /// A @ref completion_token object used to specify that an asynchronous
  626. /// operation should return a function object to lazily launch the operation.
  627. /**
  628. * See the documentation for boost::asio::deferred_t for a usage example.
  629. */
  630. constexpr deferred_t deferred;
  631. } // namespace asio
  632. } // namespace boost
  633. #include <boost/asio/detail/pop_options.hpp>
  634. #include <boost/asio/impl/deferred.hpp>
  635. #endif // BOOST_ASIO_DEFERRED_HPP