deferred.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. //
  2. // deferred.hpp
  3. // ~~~~~~~~~~~~
  4. //
  5. // Copyright (c) 2003-2024 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. conditional_t<true, initiation_t, CompletionToken>(initiation_),
  286. token, std::get<I>(init_args_)...))
  287. {
  288. return async_initiate<CompletionToken, Signature>(
  289. initiation_t(initiation_), token, std::get<I>(init_args_)...);
  290. }
  291. public:
  292. /// Construct a deferred asynchronous operation from the arguments to an
  293. /// initiation function object.
  294. template <typename I, typename... A>
  295. constexpr explicit deferred_async_operation(
  296. deferred_init_tag, I&& initiation, A&&... init_args)
  297. : initiation_(static_cast<I&&>(initiation)),
  298. init_args_(static_cast<A&&>(init_args)...)
  299. {
  300. }
  301. /// Initiate the asynchronous operation using the supplied completion token.
  302. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
  303. auto operator()(CompletionToken&& token) &&
  304. -> decltype(
  305. this->invoke_helper(
  306. static_cast<CompletionToken&&>(token),
  307. detail::index_sequence_for<InitArgs...>()))
  308. {
  309. return this->invoke_helper(
  310. static_cast<CompletionToken&&>(token),
  311. detail::index_sequence_for<InitArgs...>());
  312. }
  313. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
  314. auto operator()(CompletionToken&& token) const &
  315. -> decltype(
  316. this->const_invoke_helper(
  317. static_cast<CompletionToken&&>(token),
  318. detail::index_sequence_for<InitArgs...>()))
  319. {
  320. return this->const_invoke_helper(
  321. static_cast<CompletionToken&&>(token),
  322. detail::index_sequence_for<InitArgs...>());
  323. }
  324. };
  325. /// Encapsulates a deferred asynchronous operation thas has multiple completion
  326. /// signatures.
  327. template <typename... Signatures, typename Initiation, typename... InitArgs>
  328. class BOOST_ASIO_NODISCARD deferred_async_operation<
  329. deferred_signatures<Signatures...>, Initiation, InitArgs...>
  330. {
  331. private:
  332. typedef decay_t<Initiation> initiation_t;
  333. initiation_t initiation_;
  334. typedef std::tuple<decay_t<InitArgs>...> init_args_t;
  335. init_args_t init_args_;
  336. template <typename CompletionToken, std::size_t... I>
  337. auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
  338. -> decltype(
  339. async_initiate<CompletionToken, Signatures...>(
  340. static_cast<initiation_t&&>(initiation_), token,
  341. std::get<I>(static_cast<init_args_t&&>(init_args_))...))
  342. {
  343. return async_initiate<CompletionToken, Signatures...>(
  344. static_cast<initiation_t&&>(initiation_), token,
  345. std::get<I>(static_cast<init_args_t&&>(init_args_))...);
  346. }
  347. template <typename CompletionToken, std::size_t... I>
  348. auto const_invoke_helper(CompletionToken&& token,
  349. detail::index_sequence<I...>) const &
  350. -> decltype(
  351. async_initiate<CompletionToken, Signatures...>(
  352. initiation_t(initiation_), token, std::get<I>(init_args_)...))
  353. {
  354. return async_initiate<CompletionToken, Signatures...>(
  355. initiation_t(initiation_), token, std::get<I>(init_args_)...);
  356. }
  357. public:
  358. /// Construct a deferred asynchronous operation from the arguments to an
  359. /// initiation function object.
  360. template <typename I, typename... A>
  361. constexpr explicit deferred_async_operation(
  362. deferred_init_tag, I&& initiation, A&&... init_args)
  363. : initiation_(static_cast<I&&>(initiation)),
  364. init_args_(static_cast<A&&>(init_args)...)
  365. {
  366. }
  367. /// Initiate the asynchronous operation using the supplied completion token.
  368. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  369. auto operator()(CompletionToken&& token) &&
  370. -> decltype(
  371. this->invoke_helper(
  372. static_cast<CompletionToken&&>(token),
  373. detail::index_sequence_for<InitArgs...>()))
  374. {
  375. return this->invoke_helper(
  376. static_cast<CompletionToken&&>(token),
  377. detail::index_sequence_for<InitArgs...>());
  378. }
  379. template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
  380. auto operator()(CompletionToken&& token) const &
  381. -> decltype(
  382. this->const_invoke_helper(
  383. static_cast<CompletionToken&&>(token),
  384. detail::index_sequence_for<InitArgs...>()))
  385. {
  386. return this->const_invoke_helper(
  387. static_cast<CompletionToken&&>(token),
  388. detail::index_sequence_for<InitArgs...>());
  389. }
  390. };
  391. #if !defined(GENERATING_DOCUMENTATION)
  392. template <typename Signature, typename Initiation, typename... InitArgs>
  393. struct is_deferred<
  394. deferred_async_operation<Signature, Initiation, InitArgs...>> : true_type
  395. {
  396. };
  397. #endif // !defined(GENERATING_DOCUMENTATION)
  398. /// Defines a link between two consecutive operations in a sequence.
  399. template <typename Head, typename Tail>
  400. class BOOST_ASIO_NODISCARD deferred_sequence :
  401. public detail::deferred_sequence_types<Head, Tail>::base
  402. {
  403. public:
  404. template <typename H, typename T>
  405. constexpr explicit deferred_sequence(deferred_init_tag, H&& head, T&& tail)
  406. : detail::deferred_sequence_types<Head, Tail>::base(
  407. static_cast<H&&>(head), static_cast<T&&>(tail))
  408. {
  409. }
  410. #if defined(GENERATING_DOCUMENTATION)
  411. template <typename CompletionToken>
  412. auto operator()(CompletionToken&& token) &&;
  413. template <typename CompletionToken>
  414. auto operator()(CompletionToken&& token) const &;
  415. #endif // defined(GENERATING_DOCUMENTATION)
  416. };
  417. #if !defined(GENERATING_DOCUMENTATION)
  418. template <typename Head, typename Tail>
  419. struct is_deferred<deferred_sequence<Head, Tail>> : true_type
  420. {
  421. };
  422. #endif // !defined(GENERATING_DOCUMENTATION)
  423. /// Used to represent a deferred conditional branch.
  424. template <typename OnTrue = deferred_noop, typename OnFalse = deferred_noop>
  425. class BOOST_ASIO_NODISCARD deferred_conditional
  426. {
  427. private:
  428. template <typename T, typename F> friend class deferred_conditional;
  429. // Helper constructor.
  430. template <typename T, typename F>
  431. explicit deferred_conditional(bool b, T&& on_true, F&& on_false)
  432. : on_true_(static_cast<T&&>(on_true)),
  433. on_false_(static_cast<F&&>(on_false)),
  434. bool_(b)
  435. {
  436. }
  437. OnTrue on_true_;
  438. OnFalse on_false_;
  439. bool bool_;
  440. public:
  441. /// Construct a deferred conditional with the value to determine which branch
  442. /// will be executed.
  443. constexpr explicit deferred_conditional(bool b)
  444. : on_true_(),
  445. on_false_(),
  446. bool_(b)
  447. {
  448. }
  449. /// Invoke the conditional branch bsaed on the stored value.
  450. template <typename... Args>
  451. auto operator()(Args&&... args) &&
  452. -> decltype(static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...))
  453. {
  454. if (bool_)
  455. {
  456. return static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...);
  457. }
  458. else
  459. {
  460. return static_cast<OnFalse&&>(on_false_)(static_cast<Args&&>(args)...);
  461. }
  462. }
  463. template <typename... Args>
  464. auto operator()(Args&&... args) const &
  465. -> decltype(on_true_(static_cast<Args&&>(args)...))
  466. {
  467. if (bool_)
  468. {
  469. return on_true_(static_cast<Args&&>(args)...);
  470. }
  471. else
  472. {
  473. return on_false_(static_cast<Args&&>(args)...);
  474. }
  475. }
  476. /// Set the true branch of the conditional.
  477. template <typename T>
  478. deferred_conditional<T, OnFalse> then(T on_true,
  479. constraint_t<
  480. is_deferred<T>::value
  481. >* = 0,
  482. constraint_t<
  483. is_same<
  484. conditional_t<true, OnTrue, T>,
  485. deferred_noop
  486. >::value
  487. >* = 0) &&
  488. {
  489. return deferred_conditional<T, OnFalse>(
  490. bool_, static_cast<T&&>(on_true),
  491. static_cast<OnFalse&&>(on_false_));
  492. }
  493. /// Set the false branch of the conditional.
  494. template <typename T>
  495. deferred_conditional<OnTrue, T> otherwise(T on_false,
  496. constraint_t<
  497. is_deferred<T>::value
  498. >* = 0,
  499. constraint_t<
  500. !is_same<
  501. conditional_t<true, OnTrue, T>,
  502. deferred_noop
  503. >::value
  504. >* = 0,
  505. constraint_t<
  506. is_same<
  507. conditional_t<true, OnFalse, T>,
  508. deferred_noop
  509. >::value
  510. >* = 0) &&
  511. {
  512. return deferred_conditional<OnTrue, T>(
  513. bool_, static_cast<OnTrue&&>(on_true_),
  514. static_cast<T&&>(on_false));
  515. }
  516. };
  517. #if !defined(GENERATING_DOCUMENTATION)
  518. template <typename OnTrue, typename OnFalse>
  519. struct is_deferred<deferred_conditional<OnTrue, OnFalse>> : true_type
  520. {
  521. };
  522. #endif // !defined(GENERATING_DOCUMENTATION)
  523. /// Class used to specify that an asynchronous operation should return a
  524. /// function object to lazily launch the operation.
  525. /**
  526. * The deferred_t class is used to indicate that an asynchronous operation
  527. * should return a function object which is itself an initiation function. A
  528. * deferred_t object may be passed as a completion token to an asynchronous
  529. * operation, typically as the default completion token:
  530. *
  531. * @code auto my_deferred_op = my_socket.async_read_some(my_buffer); @endcode
  532. *
  533. * or by explicitly passing the special value @c boost::asio::deferred:
  534. *
  535. * @code auto my_deferred_op
  536. * = my_socket.async_read_some(my_buffer,
  537. * boost::asio::deferred); @endcode
  538. *
  539. * The initiating function (async_read_some in the above example) returns a
  540. * function object that will lazily initiate the operation.
  541. */
  542. class deferred_t
  543. {
  544. public:
  545. /// Default constructor.
  546. constexpr deferred_t()
  547. {
  548. }
  549. /// Adapts an executor to add the @c deferred_t completion token as the
  550. /// default.
  551. template <typename InnerExecutor>
  552. struct executor_with_default : InnerExecutor
  553. {
  554. /// Specify @c deferred_t as the default completion token type.
  555. typedef deferred_t default_completion_token_type;
  556. /// Construct the adapted executor from the inner executor type.
  557. template <typename InnerExecutor1>
  558. executor_with_default(const InnerExecutor1& ex,
  559. constraint_t<
  560. conditional_t<
  561. !is_same<InnerExecutor1, executor_with_default>::value,
  562. is_convertible<InnerExecutor1, InnerExecutor>,
  563. false_type
  564. >::value
  565. > = 0) noexcept
  566. : InnerExecutor(ex)
  567. {
  568. }
  569. };
  570. /// Type alias to adapt an I/O object to use @c deferred_t as its
  571. /// default completion token type.
  572. template <typename T>
  573. using as_default_on_t = typename T::template rebind_executor<
  574. executor_with_default<typename T::executor_type>>::other;
  575. /// Function helper to adapt an I/O object to use @c deferred_t as its
  576. /// default completion token type.
  577. template <typename T>
  578. static typename decay_t<T>::template rebind_executor<
  579. executor_with_default<typename decay_t<T>::executor_type>
  580. >::other
  581. as_default_on(T&& object)
  582. {
  583. return typename decay_t<T>::template rebind_executor<
  584. executor_with_default<typename decay_t<T>::executor_type>
  585. >::other(static_cast<T&&>(object));
  586. }
  587. /// Creates a new deferred from a function.
  588. template <typename Function>
  589. constraint_t<
  590. !is_deferred<decay_t<Function>>::value,
  591. deferred_function<decay_t<Function>>
  592. > operator()(Function&& function) const
  593. {
  594. return deferred_function<decay_t<Function>>(
  595. deferred_init_tag{}, static_cast<Function&&>(function));
  596. }
  597. /// Passes through anything that is already deferred.
  598. template <typename T>
  599. constraint_t<
  600. is_deferred<decay_t<T>>::value,
  601. decay_t<T>
  602. > operator()(T&& t) const
  603. {
  604. return static_cast<T&&>(t);
  605. }
  606. /// Returns a deferred operation that returns the provided values.
  607. template <typename... Args>
  608. static constexpr deferred_values<decay_t<Args>...> values(Args&&... args)
  609. {
  610. return deferred_values<decay_t<Args>...>(
  611. deferred_init_tag{}, static_cast<Args&&>(args)...);
  612. }
  613. /// Creates a conditional object for branching deferred operations.
  614. static constexpr deferred_conditional<> when(bool b)
  615. {
  616. return deferred_conditional<>(b);
  617. }
  618. };
  619. /// Pipe operator used to chain deferred operations.
  620. template <typename Head, typename Tail>
  621. inline auto operator|(Head head, Tail&& tail)
  622. -> constraint_t<
  623. is_deferred<Head>::value,
  624. decltype(static_cast<Head&&>(head)(static_cast<Tail&&>(tail)))
  625. >
  626. {
  627. return static_cast<Head&&>(head)(static_cast<Tail&&>(tail));
  628. }
  629. /// A @ref completion_token object used to specify that an asynchronous
  630. /// operation should return a function object to lazily launch the operation.
  631. /**
  632. * See the documentation for boost::asio::deferred_t for a usage example.
  633. */
  634. BOOST_ASIO_INLINE_VARIABLE constexpr deferred_t deferred;
  635. } // namespace asio
  636. } // namespace boost
  637. #include <boost/asio/detail/pop_options.hpp>
  638. #include <boost/asio/impl/deferred.hpp>
  639. #endif // BOOST_ASIO_DEFERRED_HPP