deferred.hpp 21 KB

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