Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-15 08:28:39

0001 //
0002 // deferred.hpp
0003 // ~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_DEFERRED_HPP
0012 #define BOOST_ASIO_DEFERRED_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <tuple>
0020 #include <boost/asio/associator.hpp>
0021 #include <boost/asio/async_result.hpp>
0022 #include <boost/asio/detail/type_traits.hpp>
0023 #include <boost/asio/detail/utility.hpp>
0024 
0025 #include <boost/asio/detail/push_options.hpp>
0026 
0027 namespace boost {
0028 namespace asio {
0029 
0030 /// Trait for detecting objects that are usable as deferred operations.
0031 template <typename T>
0032 struct is_deferred : false_type
0033 {
0034 };
0035 
0036 /// Helper type to wrap multiple completion signatures.
0037 template <typename... Signatures>
0038 struct deferred_signatures
0039 {
0040 };
0041 
0042 namespace detail {
0043 
0044 // Helper trait for getting the completion signatures of the tail in a sequence
0045 // when invoked with the specified arguments.
0046 
0047 template <typename Tail, typename... Signatures>
0048 struct deferred_sequence_signatures;
0049 
0050 template <typename Tail, typename R, typename... Args, typename... Signatures>
0051 struct deferred_sequence_signatures<Tail, R(Args...), Signatures...>
0052   : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))>
0053 {
0054   static_assert(
0055       !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,
0056       "deferred functions must produce a deferred return type");
0057 };
0058 
0059 // Completion handler for the head component of a deferred sequence.
0060 template <typename Handler, typename Tail>
0061 class deferred_sequence_handler
0062 {
0063 public:
0064   template <typename H, typename T>
0065   explicit deferred_sequence_handler(H&& handler, T&& tail)
0066     : handler_(static_cast<H&&>(handler)),
0067       tail_(static_cast<T&&>(tail))
0068   {
0069   }
0070 
0071   template <typename... Args>
0072   void operator()(Args&&... args)
0073   {
0074     static_cast<Tail&&>(tail_)(
0075         static_cast<Args&&>(args)...)(
0076           static_cast<Handler&&>(handler_));
0077   }
0078 
0079 //private:
0080   Handler handler_;
0081   Tail tail_;
0082 };
0083 
0084 template <typename Head, typename Tail, typename... Signatures>
0085 class deferred_sequence_base
0086 {
0087 private:
0088   struct initiate
0089   {
0090     template <typename Handler>
0091     void operator()(Handler&& handler, Head head, Tail&& tail)
0092     {
0093       static_cast<Head&&>(head)(
0094           deferred_sequence_handler<decay_t<Handler>, decay_t<Tail>>(
0095             static_cast<Handler&&>(handler), static_cast<Tail&&>(tail)));
0096     }
0097   };
0098 
0099   Head head_;
0100   Tail tail_;
0101 
0102 public:
0103   template <typename H, typename T>
0104   constexpr explicit deferred_sequence_base(H&& head, T&& tail)
0105     : head_(static_cast<H&&>(head)),
0106       tail_(static_cast<T&&>(tail))
0107   {
0108   }
0109 
0110   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0111   auto operator()(CompletionToken&& token) &&
0112     -> decltype(
0113       async_initiate<CompletionToken, Signatures...>(
0114         initiate(), token, static_cast<Head&&>(this->head_),
0115         static_cast<Tail&&>(this->tail_)))
0116   {
0117     return async_initiate<CompletionToken, Signatures...>(initiate(),
0118         token, static_cast<Head&&>(head_), static_cast<Tail&&>(tail_));
0119   }
0120 
0121   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0122   auto operator()(CompletionToken&& token) const &
0123     -> decltype(
0124       async_initiate<CompletionToken, Signatures...>(
0125         initiate(), token, this->head_, this->tail_))
0126   {
0127     return async_initiate<CompletionToken, Signatures...>(
0128         initiate(), token, head_, tail_);
0129   }
0130 };
0131 
0132 // Two-step application of variadic Signatures to determine correct base type.
0133 
0134 template <typename Head, typename Tail>
0135 struct deferred_sequence_types
0136 {
0137   template <typename... Signatures>
0138   struct op1
0139   {
0140     typedef deferred_sequence_base<Head, Tail, Signatures...> type;
0141   };
0142 
0143   template <typename... Signatures>
0144   struct op2
0145   {
0146     typedef typename deferred_sequence_signatures<Tail, Signatures...>::template
0147       apply<op1>::type::type type;
0148   };
0149 
0150   typedef typename completion_signature_of<Head>::template
0151     apply<op2>::type::type base;
0152 };
0153 
0154 } // namespace detail
0155 
0156 /// Used to represent an empty deferred action.
0157 struct deferred_noop
0158 {
0159   /// No effect.
0160   template <typename... Args>
0161   void operator()(Args&&...) &&
0162   {
0163   }
0164 
0165   /// No effect.
0166   template <typename... Args>
0167   void operator()(Args&&...) const &
0168   {
0169   }
0170 };
0171 
0172 #if !defined(GENERATING_DOCUMENTATION)
0173 template <>
0174 struct is_deferred<deferred_noop> : true_type
0175 {
0176 };
0177 #endif // !defined(GENERATING_DOCUMENTATION)
0178 
0179 /// Tag type to disambiguate deferred constructors.
0180 struct deferred_init_tag {};
0181 
0182 /// Wraps a function object so that it may be used as an element in a deferred
0183 /// composition.
0184 template <typename Function>
0185 class deferred_function
0186 {
0187 public:
0188   /// Constructor.
0189   template <typename F>
0190   constexpr explicit deferred_function(deferred_init_tag, F&& function)
0191     : function_(static_cast<F&&>(function))
0192   {
0193   }
0194 
0195 //private:
0196   Function function_;
0197 
0198 public:
0199   template <typename... Args>
0200   auto operator()(Args&&... args) &&
0201     -> decltype(
0202       static_cast<Function&&>(this->function_)(static_cast<Args&&>(args)...))
0203   {
0204     return static_cast<Function&&>(function_)(static_cast<Args&&>(args)...);
0205   }
0206 
0207   template <typename... Args>
0208   auto operator()(Args&&... args) const &
0209     -> decltype(Function(function_)(static_cast<Args&&>(args)...))
0210   {
0211     return Function(function_)(static_cast<Args&&>(args)...);
0212   }
0213 };
0214 
0215 #if !defined(GENERATING_DOCUMENTATION)
0216 template <typename Function>
0217 struct is_deferred<deferred_function<Function>> : true_type
0218 {
0219 };
0220 #endif // !defined(GENERATING_DOCUMENTATION)
0221 
0222 /// Encapsulates deferred values.
0223 template <typename... Values>
0224 class BOOST_ASIO_NODISCARD deferred_values
0225 {
0226 private:
0227   std::tuple<Values...> values_;
0228 
0229   struct initiate
0230   {
0231     template <typename Handler, typename... V>
0232     void operator()(Handler handler, V&&... values)
0233     {
0234       static_cast<Handler&&>(handler)(static_cast<V&&>(values)...);
0235     }
0236   };
0237 
0238   template <typename CompletionToken, std::size_t... I>
0239   auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0240     -> decltype(
0241       async_initiate<CompletionToken, void(Values...)>(initiate(), token,
0242         std::get<I>(static_cast<std::tuple<Values...>&&>(this->values_))...))
0243   {
0244     return async_initiate<CompletionToken, void(Values...)>(initiate(), token,
0245         std::get<I>(static_cast<std::tuple<Values...>&&>(values_))...);
0246   }
0247 
0248   template <typename CompletionToken, std::size_t... I>
0249   auto const_invoke_helper(CompletionToken&& token,
0250       detail::index_sequence<I...>)
0251     -> decltype(
0252       async_initiate<CompletionToken, void(Values...)>(
0253         initiate(), token, std::get<I>(values_)...))
0254   {
0255     return async_initiate<CompletionToken, void(Values...)>(
0256         initiate(), token, std::get<I>(values_)...);
0257   }
0258 
0259 public:
0260   /// Construct a deferred asynchronous operation from the arguments to an
0261   /// initiation function object.
0262   template <typename... V>
0263   constexpr explicit deferred_values(
0264       deferred_init_tag, V&&... values)
0265     : values_(static_cast<V&&>(values)...)
0266   {
0267   }
0268 
0269   /// Initiate the deferred operation using the supplied completion token.
0270   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
0271   auto operator()(CompletionToken&& token) &&
0272     -> decltype(
0273       this->invoke_helper(
0274         static_cast<CompletionToken&&>(token),
0275         detail::index_sequence_for<Values...>()))
0276   {
0277     return this->invoke_helper(
0278         static_cast<CompletionToken&&>(token),
0279         detail::index_sequence_for<Values...>());
0280   }
0281 
0282   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>
0283   auto operator()(CompletionToken&& token) const &
0284     -> decltype(
0285       this->const_invoke_helper(
0286         static_cast<CompletionToken&&>(token),
0287         detail::index_sequence_for<Values...>()))
0288   {
0289     return this->const_invoke_helper(
0290         static_cast<CompletionToken&&>(token),
0291         detail::index_sequence_for<Values...>());
0292   }
0293 };
0294 
0295 #if !defined(GENERATING_DOCUMENTATION)
0296 template <typename... Values>
0297 struct is_deferred<deferred_values<Values...>> : true_type
0298 {
0299 };
0300 #endif // !defined(GENERATING_DOCUMENTATION)
0301 
0302 /// Encapsulates a deferred asynchronous operation.
0303 template <typename Signature, typename Initiation, typename... InitArgs>
0304 class BOOST_ASIO_NODISCARD deferred_async_operation
0305 {
0306 private:
0307   typedef decay_t<Initiation> initiation_t;
0308   initiation_t initiation_;
0309   typedef std::tuple<decay_t<InitArgs>...> init_args_t;
0310   init_args_t init_args_;
0311 
0312   template <typename CompletionToken, std::size_t... I>
0313   auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0314     -> decltype(
0315       async_initiate<CompletionToken, Signature>(
0316         static_cast<initiation_t&&>(initiation_), token,
0317         std::get<I>(static_cast<init_args_t&&>(init_args_))...))
0318   {
0319     return async_initiate<CompletionToken, Signature>(
0320         static_cast<initiation_t&&>(initiation_), token,
0321         std::get<I>(static_cast<init_args_t&&>(init_args_))...);
0322   }
0323 
0324   template <typename CompletionToken, std::size_t... I>
0325   auto const_invoke_helper(CompletionToken&& token,
0326       detail::index_sequence<I...>) const &
0327     -> decltype(
0328       async_initiate<CompletionToken, Signature>(
0329         conditional_t<true, initiation_t, CompletionToken>(initiation_),
0330         token, std::get<I>(init_args_)...))
0331   {
0332     return async_initiate<CompletionToken, Signature>(
0333         initiation_t(initiation_), token, std::get<I>(init_args_)...);
0334   }
0335 
0336 public:
0337   /// Construct a deferred asynchronous operation from the arguments to an
0338   /// initiation function object.
0339   template <typename I, typename... A>
0340   constexpr explicit deferred_async_operation(
0341       deferred_init_tag, I&& initiation, A&&... init_args)
0342     : initiation_(static_cast<I&&>(initiation)),
0343       init_args_(static_cast<A&&>(init_args)...)
0344   {
0345   }
0346 
0347   /// Initiate the asynchronous operation using the supplied completion token.
0348   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
0349   auto operator()(CompletionToken&& token) &&
0350     -> decltype(
0351       this->invoke_helper(
0352         static_cast<CompletionToken&&>(token),
0353         detail::index_sequence_for<InitArgs...>()))
0354   {
0355     return this->invoke_helper(
0356         static_cast<CompletionToken&&>(token),
0357         detail::index_sequence_for<InitArgs...>());
0358   }
0359 
0360   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>
0361   auto operator()(CompletionToken&& token) const &
0362     -> decltype(
0363       this->const_invoke_helper(
0364         static_cast<CompletionToken&&>(token),
0365         detail::index_sequence_for<InitArgs...>()))
0366   {
0367     return this->const_invoke_helper(
0368         static_cast<CompletionToken&&>(token),
0369         detail::index_sequence_for<InitArgs...>());
0370   }
0371 };
0372 
0373 /// Encapsulates a deferred asynchronous operation thas has multiple completion
0374 /// signatures.
0375 template <typename... Signatures, typename Initiation, typename... InitArgs>
0376 class BOOST_ASIO_NODISCARD deferred_async_operation<
0377     deferred_signatures<Signatures...>, Initiation, InitArgs...>
0378 {
0379 private:
0380   typedef decay_t<Initiation> initiation_t;
0381   initiation_t initiation_;
0382   typedef std::tuple<decay_t<InitArgs>...> init_args_t;
0383   init_args_t init_args_;
0384 
0385   template <typename CompletionToken, std::size_t... I>
0386   auto invoke_helper(CompletionToken&& token, detail::index_sequence<I...>)
0387     -> decltype(
0388       async_initiate<CompletionToken, Signatures...>(
0389         static_cast<initiation_t&&>(initiation_), token,
0390         std::get<I>(static_cast<init_args_t&&>(init_args_))...))
0391   {
0392     return async_initiate<CompletionToken, Signatures...>(
0393         static_cast<initiation_t&&>(initiation_), token,
0394         std::get<I>(static_cast<init_args_t&&>(init_args_))...);
0395   }
0396 
0397   template <typename CompletionToken, std::size_t... I>
0398   auto const_invoke_helper(CompletionToken&& token,
0399       detail::index_sequence<I...>) const &
0400     -> decltype(
0401       async_initiate<CompletionToken, Signatures...>(
0402         initiation_t(initiation_), token, std::get<I>(init_args_)...))
0403   {
0404     return async_initiate<CompletionToken, Signatures...>(
0405         initiation_t(initiation_), token, std::get<I>(init_args_)...);
0406   }
0407 
0408 public:
0409   /// Construct a deferred asynchronous operation from the arguments to an
0410   /// initiation function object.
0411   template <typename I, typename... A>
0412   constexpr explicit deferred_async_operation(
0413       deferred_init_tag, I&& initiation, A&&... init_args)
0414     : initiation_(static_cast<I&&>(initiation)),
0415       init_args_(static_cast<A&&>(init_args)...)
0416   {
0417   }
0418 
0419   /// Initiate the asynchronous operation using the supplied completion token.
0420   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0421   auto operator()(CompletionToken&& token) &&
0422     -> decltype(
0423       this->invoke_helper(
0424         static_cast<CompletionToken&&>(token),
0425         detail::index_sequence_for<InitArgs...>()))
0426   {
0427     return this->invoke_helper(
0428         static_cast<CompletionToken&&>(token),
0429         detail::index_sequence_for<InitArgs...>());
0430   }
0431 
0432   template <BOOST_ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>
0433   auto operator()(CompletionToken&& token) const &
0434     -> decltype(
0435       this->const_invoke_helper(
0436         static_cast<CompletionToken&&>(token),
0437         detail::index_sequence_for<InitArgs...>()))
0438   {
0439     return this->const_invoke_helper(
0440         static_cast<CompletionToken&&>(token),
0441         detail::index_sequence_for<InitArgs...>());
0442   }
0443 };
0444 
0445 #if !defined(GENERATING_DOCUMENTATION)
0446 template <typename Signature, typename Initiation, typename... InitArgs>
0447 struct is_deferred<
0448     deferred_async_operation<Signature, Initiation, InitArgs...>> : true_type
0449 {
0450 };
0451 #endif // !defined(GENERATING_DOCUMENTATION)
0452 
0453 /// Defines a link between two consecutive operations in a sequence.
0454 template <typename Head, typename Tail>
0455 class BOOST_ASIO_NODISCARD deferred_sequence :
0456   public detail::deferred_sequence_types<Head, Tail>::base
0457 {
0458 public:
0459   template <typename H, typename T>
0460   constexpr explicit deferred_sequence(deferred_init_tag, H&& head, T&& tail)
0461     : detail::deferred_sequence_types<Head, Tail>::base(
0462         static_cast<H&&>(head), static_cast<T&&>(tail))
0463   {
0464   }
0465 
0466 #if defined(GENERATING_DOCUMENTATION)
0467   template <typename CompletionToken>
0468   auto operator()(CompletionToken&& token) &&;
0469 
0470   template <typename CompletionToken>
0471   auto operator()(CompletionToken&& token) const &;
0472 #endif // defined(GENERATING_DOCUMENTATION)
0473 };
0474 
0475 #if !defined(GENERATING_DOCUMENTATION)
0476 template <typename Head, typename Tail>
0477 struct is_deferred<deferred_sequence<Head, Tail>> : true_type
0478 {
0479 };
0480 #endif // !defined(GENERATING_DOCUMENTATION)
0481 
0482 /// Used to represent a deferred conditional branch.
0483 template <typename OnTrue = deferred_noop, typename OnFalse = deferred_noop>
0484 class BOOST_ASIO_NODISCARD deferred_conditional
0485 {
0486 private:
0487   template <typename T, typename F> friend class deferred_conditional;
0488 
0489   // Helper constructor.
0490   template <typename T, typename F>
0491   explicit deferred_conditional(bool b, T&& on_true, F&& on_false)
0492     : on_true_(static_cast<T&&>(on_true)),
0493       on_false_(static_cast<F&&>(on_false)),
0494       bool_(b)
0495   {
0496   }
0497 
0498   OnTrue on_true_;
0499   OnFalse on_false_;
0500   bool bool_;
0501 
0502 public:
0503   /// Construct a deferred conditional with the value to determine which branch
0504   /// will be executed.
0505   constexpr explicit deferred_conditional(bool b)
0506     : on_true_(),
0507       on_false_(),
0508       bool_(b)
0509   {
0510   }
0511 
0512   /// Invoke the conditional branch bsaed on the stored value.
0513   template <typename... Args>
0514   auto operator()(Args&&... args) &&
0515     -> decltype(static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...))
0516   {
0517     if (bool_)
0518     {
0519       return static_cast<OnTrue&&>(on_true_)(static_cast<Args&&>(args)...);
0520     }
0521     else
0522     {
0523       return static_cast<OnFalse&&>(on_false_)(static_cast<Args&&>(args)...);
0524     }
0525   }
0526 
0527   template <typename... Args>
0528   auto operator()(Args&&... args) const &
0529     -> decltype(on_true_(static_cast<Args&&>(args)...))
0530   {
0531     if (bool_)
0532     {
0533       return on_true_(static_cast<Args&&>(args)...);
0534     }
0535     else
0536     {
0537       return on_false_(static_cast<Args&&>(args)...);
0538     }
0539   }
0540 
0541   /// Set the true branch of the conditional.
0542   template <typename T>
0543   deferred_conditional<T, OnFalse> then(T on_true,
0544       constraint_t<
0545         is_deferred<T>::value
0546       >* = 0,
0547       constraint_t<
0548         is_same<
0549           conditional_t<true, OnTrue, T>,
0550           deferred_noop
0551         >::value
0552       >* = 0) &&
0553   {
0554     return deferred_conditional<T, OnFalse>(
0555         bool_, static_cast<T&&>(on_true),
0556         static_cast<OnFalse&&>(on_false_));
0557   }
0558 
0559   /// Set the false branch of the conditional.
0560   template <typename T>
0561   deferred_conditional<OnTrue, T> otherwise(T on_false,
0562       constraint_t<
0563         is_deferred<T>::value
0564       >* = 0,
0565       constraint_t<
0566         !is_same<
0567           conditional_t<true, OnTrue, T>,
0568           deferred_noop
0569         >::value
0570       >* = 0,
0571       constraint_t<
0572         is_same<
0573           conditional_t<true, OnFalse, T>,
0574           deferred_noop
0575         >::value
0576       >* = 0) &&
0577   {
0578     return deferred_conditional<OnTrue, T>(
0579         bool_, static_cast<OnTrue&&>(on_true_),
0580         static_cast<T&&>(on_false));
0581   }
0582 };
0583 
0584 #if !defined(GENERATING_DOCUMENTATION)
0585 template <typename OnTrue, typename OnFalse>
0586 struct is_deferred<deferred_conditional<OnTrue, OnFalse>> : true_type
0587 {
0588 };
0589 #endif // !defined(GENERATING_DOCUMENTATION)
0590 
0591 /// Class used to specify that an asynchronous operation should return a
0592 /// function object to lazily launch the operation.
0593 /**
0594  * The deferred_t class is used to indicate that an asynchronous operation
0595  * should return a function object which is itself an initiation function. A
0596  * deferred_t object may be passed as a completion token to an asynchronous
0597  * operation, typically as the default completion token:
0598  *
0599  * @code auto my_deferred_op = my_socket.async_read_some(my_buffer); @endcode
0600  *
0601  * or by explicitly passing the special value @c boost::asio::deferred:
0602  *
0603  * @code auto my_deferred_op
0604  *   = my_socket.async_read_some(my_buffer,
0605  *       boost::asio::deferred); @endcode
0606  *
0607  * The initiating function (async_read_some in the above example) returns a
0608  * function object that will lazily initiate the operation.
0609  */
0610 class deferred_t
0611 {
0612 public:
0613   /// Default constructor.
0614   constexpr deferred_t()
0615   {
0616   }
0617 
0618   /// Adapts an executor to add the @c deferred_t completion token as the
0619   /// default.
0620   template <typename InnerExecutor>
0621   struct executor_with_default : InnerExecutor
0622   {
0623     /// Specify @c deferred_t as the default completion token type.
0624     typedef deferred_t default_completion_token_type;
0625 
0626     /// Construct the adapted executor from the inner executor type.
0627     template <typename InnerExecutor1>
0628     executor_with_default(const InnerExecutor1& ex,
0629         constraint_t<
0630           conditional_t<
0631             !is_same<InnerExecutor1, executor_with_default>::value,
0632             is_convertible<InnerExecutor1, InnerExecutor>,
0633             false_type
0634           >::value
0635         > = 0) noexcept
0636       : InnerExecutor(ex)
0637     {
0638     }
0639   };
0640 
0641   /// Type alias to adapt an I/O object to use @c deferred_t as its
0642   /// default completion token type.
0643   template <typename T>
0644   using as_default_on_t = typename T::template rebind_executor<
0645       executor_with_default<typename T::executor_type>>::other;
0646 
0647   /// Function helper to adapt an I/O object to use @c deferred_t as its
0648   /// default completion token type.
0649   template <typename T>
0650   static typename decay_t<T>::template rebind_executor<
0651       executor_with_default<typename decay_t<T>::executor_type>
0652     >::other
0653   as_default_on(T&& object)
0654   {
0655     return typename decay_t<T>::template rebind_executor<
0656         executor_with_default<typename decay_t<T>::executor_type>
0657       >::other(static_cast<T&&>(object));
0658   }
0659 
0660   /// Creates a new deferred from a function.
0661   template <typename Function>
0662   constraint_t<
0663     !is_deferred<decay_t<Function>>::value,
0664     deferred_function<decay_t<Function>>
0665   > operator()(Function&& function) const
0666   {
0667     return deferred_function<decay_t<Function>>(
0668         deferred_init_tag{}, static_cast<Function&&>(function));
0669   }
0670 
0671   /// Passes through anything that is already deferred.
0672   template <typename T>
0673   constraint_t<
0674     is_deferred<decay_t<T>>::value,
0675     decay_t<T>
0676   > operator()(T&& t) const
0677   {
0678     return static_cast<T&&>(t);
0679   }
0680 
0681   /// Returns a deferred operation that returns the provided values.
0682   template <typename... Args>
0683   static constexpr deferred_values<decay_t<Args>...> values(Args&&... args)
0684   {
0685     return deferred_values<decay_t<Args>...>(
0686         deferred_init_tag{}, static_cast<Args&&>(args)...);
0687   }
0688 
0689   /// Creates a conditional object for branching deferred operations.
0690   static constexpr deferred_conditional<> when(bool b)
0691   {
0692     return deferred_conditional<>(b);
0693   }
0694 };
0695 
0696 /// Pipe operator used to chain deferred operations.
0697 template <typename Head, typename Tail>
0698 inline auto operator|(Head head, Tail&& tail)
0699   -> constraint_t<
0700       is_deferred<Head>::value,
0701       decltype(static_cast<Head&&>(head)(static_cast<Tail&&>(tail)))
0702     >
0703 {
0704   return static_cast<Head&&>(head)(static_cast<Tail&&>(tail));
0705 }
0706 
0707 /// A @ref completion_token object used to specify that an asynchronous
0708 /// operation should return a function object to lazily launch the operation.
0709 /**
0710  * See the documentation for boost::asio::deferred_t for a usage example.
0711  */
0712 BOOST_ASIO_INLINE_VARIABLE constexpr deferred_t deferred;
0713 
0714 } // namespace asio
0715 } // namespace boost
0716 
0717 #include <boost/asio/detail/pop_options.hpp>
0718 
0719 #include <boost/asio/impl/deferred.hpp>
0720 
0721 #endif // BOOST_ASIO_DEFERRED_HPP