Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-17 08:38:33

0001 //
0002 // inline_or_executor.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 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_INLINE_OR_EXECUTOR_HPP
0012 #define BOOST_ASIO_INLINE_OR_EXECUTOR_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 <boost/asio/detail/non_const_lvalue.hpp>
0020 #include <boost/asio/detail/type_traits.hpp>
0021 #include <boost/asio/execution/blocking.hpp>
0022 #include <boost/asio/execution/executor.hpp>
0023 #include <boost/asio/execution/inline_exception_handling.hpp>
0024 #include <boost/asio/execution_context.hpp>
0025 #include <boost/asio/is_executor.hpp>
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 
0032 /// Adapts an executor to add inline invocation of the submitted function.
0033 /**
0034  * The @c inline_or_executor class template adapts an existing executor such
0035  * that:
0036  *
0037  * @li posted function objects (or when the @c blocking property is set to
0038  * @c blocking.never) are submitted to the wrapped executor; and
0039  *
0040  * @li dispatched function objects (or when @c blocking is @c blocking.always or
0041  * @c blocking.possibly) are executed inline.
0042  */
0043 template <typename Executor,
0044     typename Blocking = execution::blocking_t::always_t,
0045     typename InlineExceptionHandling
0046       = execution::inline_exception_handling_t::propagate_t>
0047 class inline_or_executor
0048 {
0049 public:
0050   /// The type of the underlying executor.
0051   typedef Executor inner_executor_type;
0052 
0053   /// Default constructor.
0054   /**
0055    * This constructor is only valid if the underlying executor type is default
0056    * constructible.
0057    */
0058   inline_or_executor()
0059     : executor_()
0060   {
0061   }
0062 
0063   /// Construct an inline_or_executor for the specified executor.
0064   template <typename Executor1>
0065   explicit inline_or_executor(const Executor1& e,
0066       constraint_t<
0067         conditional_t<
0068           !is_same<Executor1, inline_or_executor>::value,
0069           is_convertible<Executor1, Executor>,
0070           false_type
0071         >::value
0072       > = 0)
0073     : executor_(e)
0074   {
0075   }
0076 
0077   /// Copy constructor.
0078   inline_or_executor(const inline_or_executor& other) noexcept
0079     : executor_(other.executor_)
0080   {
0081   }
0082 
0083   /// Converting constructor.
0084   /**
0085    * This constructor is only valid if the @c OtherExecutor type is convertible
0086    * to @c Executor.
0087    */
0088   template <class OtherExecutor>
0089   inline_or_executor(
0090       const inline_or_executor<OtherExecutor>& other) noexcept
0091     : executor_(other.executor_)
0092   {
0093   }
0094 
0095   /// Assignment operator.
0096   inline_or_executor& operator=(const inline_or_executor& other) noexcept
0097   {
0098     executor_ = other.executor_;
0099     return *this;
0100   }
0101 
0102   /// Converting assignment operator.
0103   /**
0104    * This assignment operator is only valid if the @c OtherExecutor type is
0105    * convertible to @c Executor.
0106    */
0107   template <class OtherExecutor>
0108   inline_or_executor& operator=(
0109       const inline_or_executor<OtherExecutor>& other) noexcept
0110   {
0111     executor_ = other.executor_;
0112     return *this;
0113   }
0114 
0115   /// Move constructor.
0116   inline_or_executor(inline_or_executor&& other) noexcept
0117     : executor_(static_cast<Executor&&>(other.executor_))
0118   {
0119   }
0120 
0121   /// Converting move constructor.
0122   /**
0123    * This constructor is only valid if the @c OtherExecutor type is convertible
0124    * to @c Executor.
0125    */
0126   template <class OtherExecutor>
0127   inline_or_executor(inline_or_executor<OtherExecutor>&& other) noexcept
0128     : executor_(static_cast<OtherExecutor&&>(other.executor_))
0129   {
0130   }
0131 
0132   /// Move assignment operator.
0133   inline_or_executor& operator=(inline_or_executor&& other) noexcept
0134   {
0135     executor_ = static_cast<Executor&&>(other.executor_);
0136     return *this;
0137   }
0138 
0139   /// Converting move assignment operator.
0140   /**
0141    * This assignment operator is only valid if the @c OtherExecutor type is
0142    * convertible to @c Executor.
0143    */
0144   template <class OtherExecutor>
0145   inline_or_executor& operator=(
0146       inline_or_executor<OtherExecutor>&& other) noexcept
0147   {
0148     executor_ = static_cast<OtherExecutor&&>(other.executor_);
0149     return *this;
0150   }
0151 
0152   /// Destructor.
0153   ~inline_or_executor() noexcept
0154   {
0155   }
0156 
0157   /// Obtain the underlying executor.
0158   inner_executor_type get_inner_executor() const noexcept
0159   {
0160     return executor_;
0161   }
0162 
0163   /// Query the current value of the @c blocking property.
0164   /**
0165    * Do not call this function directly. It is intended for use with the
0166    * boost::asio::query customisation point.
0167    *
0168    * For example:
0169    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0170    * if (boost::asio::query(ex, boost::asio::execution::blocking)
0171    *     == boost::asio::execution::blocking.possibly)
0172    *   ... @endcode
0173    */
0174   static constexpr execution::blocking_t query(execution::blocking_t) noexcept
0175   {
0176     return Blocking();
0177   }
0178 
0179   /// Query the current value of the @c inline_exception_handling property.
0180   /**
0181    * Do not call this function directly. It is intended for use with the
0182    * boost::asio::query customisation point.
0183    *
0184    * For example:
0185    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0186    * if (boost::asio::query(ex,
0187    *       boost::asio::execution::inline_exception_handling)
0188    *     == boost::asio::execution::inline_exception_handling.propagate)
0189    *   ... @endcode
0190    */
0191   static constexpr execution::inline_exception_handling_t query(
0192       execution::inline_exception_handling_t) noexcept
0193   {
0194     return InlineExceptionHandling();
0195   }
0196 
0197   /// Forward a query to the underlying executor.
0198   /**
0199    * Do not call this function directly. It is intended for use with the
0200    * boost::asio::query customisation point.
0201    *
0202    * For example:
0203    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0204    * if (boost::asio::query(ex, boost::asio::execution::blocking)
0205    *       == boost::asio::execution::blocking.never)
0206    *   ... @endcode
0207    */
0208   template <typename Property>
0209   query_result_t<const Executor&, Property> query(const Property& p,
0210       constraint_t<
0211         can_query<const Executor&, Property>::value
0212       > = 0,
0213       constraint_t<
0214         !is_convertible<Property, execution::blocking_t>::value
0215       > = 0,
0216       constraint_t<
0217         !is_convertible<Property, execution::inline_exception_handling_t>::value
0218       > = 0) const
0219     noexcept(is_nothrow_query<const Executor&, Property>::value)
0220   {
0221     return boost::asio::query(executor_, p);
0222   }
0223 
0224   /// Obtain an executor with the @c blocking.possibly property.
0225   /**
0226    * Do not call this function directly. It is intended for use with the
0227    * boost::asio::require customisation point.
0228    *
0229    * For example:
0230    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0231    * auto ex2 = boost::asio::require(ex1,
0232    *     boost::asio::execution::blocking.possibly); @endcode
0233    */
0234   inline_or_executor<Executor, execution::blocking_t::possibly_t,
0235       InlineExceptionHandling>
0236   require(const execution::blocking_t::possibly_t&) const noexcept
0237   {
0238     return inline_or_executor<Executor, execution::blocking_t::possibly_t,
0239         InlineExceptionHandling>(executor_);
0240   }
0241 
0242   /// Obtain an executor with the @c blocking.always property.
0243   /**
0244    * Do not call this function directly. It is intended for use with the
0245    * boost::asio::require customisation point.
0246    *
0247    * For example:
0248    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0249    * auto ex2 = boost::asio::require(ex1,
0250    *     boost::asio::execution::blocking.always); @endcode
0251    */
0252   inline_or_executor<Executor, execution::blocking_t::always_t,
0253       InlineExceptionHandling>
0254   require(const execution::blocking_t::always_t&) const noexcept
0255   {
0256     return inline_or_executor<Executor, execution::blocking_t::always_t,
0257         InlineExceptionHandling>(executor_);
0258   }
0259 
0260   /// Obtain an executor with the @c blocking.never property.
0261   /**
0262    * Do not call this function directly. It is intended for use with the
0263    * boost::asio::require customisation point.
0264    *
0265    * For example:
0266    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0267    * auto ex2 = boost::asio::require(ex1,
0268    *     boost::asio::execution::blocking.never); @endcode
0269    */
0270   inline_or_executor<Executor, execution::blocking_t::never_t,
0271       InlineExceptionHandling>
0272   require(const execution::blocking_t::never_t&) const noexcept
0273   {
0274     return inline_or_executor<Executor, execution::blocking_t::never_t,
0275         InlineExceptionHandling>(executor_);
0276   }
0277 
0278   /// Obtain an executor with the @c inline_exception_handling.propagate
0279   /// property.
0280   /**
0281    * Do not call this function directly. It is intended for use with the
0282    * boost::asio::require customisation point.
0283    *
0284    * For example:
0285    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0286    * auto ex2 = boost::asio::require(ex1,
0287    *     boost::asio::execution::inline_exception_handling.propagate); @endcode
0288    */
0289   inline_or_executor<Executor, Blocking,
0290       execution::inline_exception_handling_t::propagate_t>
0291   require(const execution::inline_exception_handling_t::propagate_t&)
0292     const noexcept
0293   {
0294     return inline_or_executor<Executor, Blocking,
0295         execution::inline_exception_handling_t::propagate_t>(executor_);
0296   }
0297 
0298   /// Obtain an executor with the @c inline_exception_handling.terminate
0299   /// property.
0300   /**
0301    * Do not call this function directly. It is intended for use with the
0302    * boost::asio::require customisation point.
0303    *
0304    * For example:
0305    * @code boost::asio::inline_or_executor<my_executor_type> ex = ...;
0306    * auto ex2 = boost::asio::require(ex1,
0307    *     boost::asio::execution::inline_exception_handling.terminate); @endcode
0308    */
0309   inline_or_executor<Executor, Blocking,
0310       execution::inline_exception_handling_t::terminate_t>
0311   require(const execution::inline_exception_handling_t::terminate_t&)
0312     const noexcept
0313   {
0314     return inline_or_executor<Executor, Blocking,
0315         execution::inline_exception_handling_t::terminate_t>(executor_);
0316   }
0317 
0318   /// Forward a requirement to the underlying executor.
0319   /**
0320    * Do not call this function directly. It is intended for use with the
0321    * boost::asio::require customisation point.
0322    *
0323    * For example:
0324    * @code boost::asio::inline_or_executor<my_executor_type> ex1 = ...;
0325    * auto ex2 = boost::asio::require(ex1,
0326    *     boost::asio::execution::relationship.continuation); @endcode
0327    */
0328   template <typename Property>
0329   inline_or_executor<decay_t<require_result_t<const Executor&, Property>>,
0330       Blocking, InlineExceptionHandling>
0331   require(const Property& p,
0332       constraint_t<
0333         can_require<const Executor&, Property>::value
0334       > = 0,
0335       constraint_t<
0336         !is_convertible<Property, execution::blocking_t>::value
0337       > = 0,
0338       constraint_t<
0339         !is_convertible<Property, execution::inline_exception_handling_t>::value
0340       > = 0) const
0341     noexcept(is_nothrow_require<const Executor&, Property>::value)
0342   {
0343     return inline_or_executor<
0344         decay_t<require_result_t<const Executor&, Property>>,
0345         Blocking, InlineExceptionHandling>(boost::asio::require(executor_, p));
0346   }
0347 
0348   /// Forward a preference to the underlying executor.
0349   /**
0350    * Do not call this function directly. It is intended for use with the
0351    * boost::asio::prefer customisation point.
0352    *
0353    * For example:
0354    * @code boost::asio::inline_or_executor<my_executor_type> ex1 = ...;
0355    * auto ex2 = boost::asio::prefer(ex1,
0356    *     boost::asio::execution::relationship.continuation); @endcode
0357    */
0358   template <typename Property>
0359   inline_or_executor<decay_t<prefer_result_t<const Executor&, Property>>,
0360       Blocking, InlineExceptionHandling>
0361   prefer(const Property& p,
0362       constraint_t<
0363         can_prefer<const Executor&, Property>::value
0364       > = 0,
0365       constraint_t<
0366         !is_convertible<Property, execution::blocking_t>::value
0367       > = 0,
0368       constraint_t<
0369         !is_convertible<Property, execution::inline_exception_handling_t>::value
0370       > = 0) const
0371     noexcept(is_nothrow_prefer<const Executor&, Property>::value)
0372   {
0373     return inline_or_executor<
0374         decay_t<prefer_result_t<const Executor&, Property>>,
0375         Blocking, InlineExceptionHandling>(boost::asio::prefer(executor_, p));
0376   }
0377 
0378 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0379   /// Obtain the underlying execution context.
0380   execution_context& context() const noexcept
0381   {
0382     return executor_.context();
0383   }
0384 
0385   /// Inform the inline_or_executor that it has some outstanding work to do.
0386   /**
0387    * The inline_or_executor delegates this call to its underlying executor.
0388    */
0389   void on_work_started() const noexcept
0390   {
0391     executor_.on_work_started();
0392   }
0393 
0394   /// Inform the inline_or_executor that some work is no longer outstanding.
0395   /**
0396    * The inline_or_executor delegates this call to its underlying executor.
0397    */
0398   void on_work_finished() const noexcept
0399   {
0400     executor_.on_work_finished();
0401   }
0402 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0403 
0404   /// Request the inline_or_executor to invoke the given function object.
0405   /**
0406    * This function is used to ask the inline_or_executor to execute the given
0407    * function object. The function object will be executed inline or according
0408    * to the properties of the underlying executor.
0409    *
0410    * @param f The function object to be called. The executor will make
0411    * a copy of the handler object as required. The function signature of the
0412    * function object must be: @code void function(); @endcode
0413    */
0414   template <typename Function>
0415   constraint_t<
0416     traits::execute_member<const Executor&, Function>::is_valid,
0417     void
0418   > execute(Function&& f) const
0419   {
0420     this->execute_helper(static_cast<Function&&>(f), Blocking{});
0421   }
0422 
0423 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0424   /// Request the inline_or_executor to invoke the given function object.
0425   /**
0426    * This function is used to ask the inline_or_executor to execute the given
0427    * function object. The function object will be executed inside this function.
0428    *
0429    * @param f The function object to be called. The executor will make
0430    * a copy of the handler object as required. The function signature of the
0431    * function object must be: @code void function(); @endcode
0432    *
0433    * @param a An allocator that may be used by the executor to allocate the
0434    * internal storage needed for function invocation.
0435    */
0436   template <typename Function, typename Allocator>
0437   void dispatch(Function&& f, const Allocator& a) const
0438   {
0439     (void)a;
0440     detail::non_const_lvalue<Function> f2(f);
0441     static_cast<decay_t<Function>&&>(f2.value)();
0442   }
0443 
0444   /// Request the inline_or_executor to invoke the given function object.
0445   /**
0446    * This function is used to ask the executor to execute the given function
0447    * object. The function object will never be executed inside this function.
0448    * Instead, it will be scheduled by the underlying executor's post function.
0449    *
0450    * @param f The function object to be called. The executor will make
0451    * a copy of the handler object as required. The function signature of the
0452    * function object must be: @code void function(); @endcode
0453    *
0454    * @param a An allocator that may be used by the executor to allocate the
0455    * internal storage needed for function invocation.
0456    */
0457   template <typename Function, typename Allocator>
0458   void post(Function&& f, const Allocator& a) const
0459   {
0460     executor_.post(static_cast<Function&&>(f), a);
0461   }
0462 
0463   /// Request the inline_or_executor to invoke the given function object.
0464   /**
0465    * This function is used to ask the executor to execute the given function
0466    * object. The function object will never be executed inside this function.
0467    * Instead, it will be scheduled by the underlying executor's defer function.
0468    *
0469    * @param f The function object to be called. The executor will make
0470    * a copy of the handler object as required. The function signature of the
0471    * function object must be: @code void function(); @endcode
0472    *
0473    * @param a An allocator that may be used by the executor to allocate the
0474    * internal storage needed for function invocation.
0475    */
0476   template <typename Function, typename Allocator>
0477   void defer(Function&& f, const Allocator& a) const
0478   {
0479     executor_.defer(static_cast<Function&&>(f), a);
0480   }
0481 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0482 
0483   /// Compare two inline_or_executors for equality.
0484   /**
0485    * Two inline_or_executors are equal if their underlying executors are equal.
0486    */
0487   friend bool operator==(const inline_or_executor& a,
0488       const inline_or_executor& b) noexcept
0489   {
0490     return a.executor_ == b.executor_;
0491   }
0492 
0493   /// Compare two inline_or_executors for inequality.
0494   /**
0495    * Two inline_or_executors are equal if their underlying executors are equal.
0496    */
0497   friend bool operator!=(const inline_or_executor& a,
0498       const inline_or_executor& b) noexcept
0499   {
0500     return a.executor_ != b.executor_;
0501   }
0502 
0503 #if defined(GENERATING_DOCUMENTATION)
0504 private:
0505 #endif // defined(GENERATING_DOCUMENTATION)
0506   template <typename Function>
0507   void execute_helper(Function&& f, execution::blocking_t::possibly_t) const
0508   {
0509 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0510     try
0511 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
0512     {
0513       detail::non_const_lvalue<Function> f2(f);
0514       static_cast<decay_t<Function>&&>(f2.value)();
0515     }
0516 #if !defined(BOOST_ASIO_NO_EXCEPTIONS)
0517     catch (...)
0518     {
0519       if (is_same<InlineExceptionHandling,
0520           execution::inline_exception_handling_t::terminate_t>::value)
0521       {
0522         std::terminate();
0523       }
0524       else
0525       {
0526         throw;
0527       }
0528     }
0529 #endif // !defined(BOOST_ASIO_NO_EXCEPTIONS)
0530   }
0531 
0532   template <typename Function>
0533   void execute_helper(Function&& f, execution::blocking_t::always_t) const
0534   {
0535     this->execute_helper(static_cast<Function&&>(f),
0536         execution::blocking.possibly);
0537   }
0538 
0539   template <typename Function>
0540   void execute_helper(Function&& f, execution::blocking_t::never_t) const
0541   {
0542     boost::asio::require(executor_, execution::blocking.never).execute(
0543         static_cast<Function&&>(f));
0544   }
0545 
0546   Executor executor_;
0547 };
0548 
0549 /** @defgroup inline_or boost::asio::inline_or
0550  *
0551  * @brief The boost::asio::inline_or function creates an @ref inline_or_executor
0552  * object for an executor or execution context.
0553  */
0554 /*@{*/
0555 
0556 /// Create an @ref inline_or_executor object for an executor.
0557 /**
0558  * @param ex An executor.
0559  *
0560  * @returns An inline_or_executor constructed with the specified executor.
0561  */
0562 template <typename Executor>
0563 inline inline_or_executor<Executor> inline_or(const Executor& ex,
0564     constraint_t<
0565       is_executor<Executor>::value || execution::is_executor<Executor>::value
0566     > = 0)
0567 {
0568   return inline_or_executor<Executor>(ex);
0569 }
0570 
0571 /// Create an @ref inline_or_executor object for an execution context.
0572 /**
0573  * @param ctx An execution context, from which an executor will be obtained.
0574  *
0575  * @returns An inline_or_executor constructed with the execution context's
0576  * executor, obtained by performing <tt>ctx.get_executor()</tt>.
0577  */
0578 template <typename ExecutionContext>
0579 inline inline_or_executor<typename ExecutionContext::executor_type>
0580 inline_or(ExecutionContext& ctx,
0581     constraint_t<
0582       is_convertible<ExecutionContext&, execution_context&>::value
0583     > = 0)
0584 {
0585   return inline_or_executor<typename ExecutionContext::executor_type>(
0586       ctx.get_executor());
0587 }
0588 
0589 /*@}*/
0590 
0591 #if !defined(GENERATING_DOCUMENTATION)
0592 
0593 namespace traits {
0594 
0595 #if !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0596 
0597 template <typename Executor, typename Blocking,
0598     typename InlineExceptionHandling>
0599 struct equality_comparable<
0600     inline_or_executor<Executor, Blocking, InlineExceptionHandling>>
0601 {
0602   static constexpr bool is_valid = true;
0603   static constexpr bool is_noexcept = true;
0604 };
0605 
0606 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)
0607 
0608 #if !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0609 
0610 template <typename Executor, typename Blocking,
0611     typename InlineExceptionHandling, typename Function>
0612 struct execute_member<
0613     inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Function,
0614     enable_if_t<
0615       traits::execute_member<const Executor&, Function>::is_valid
0616     >
0617   >
0618 {
0619   static constexpr bool is_valid = true;
0620   static constexpr bool is_noexcept = false;
0621   typedef void result_type;
0622 };
0623 
0624 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)
0625 
0626 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0627 
0628 template <typename Executor, typename Blocking,
0629     typename InlineExceptionHandling, typename Property>
0630 struct query_static_constexpr_member<
0631     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0632     Property,
0633     enable_if_t<
0634       is_convertible<
0635         Property,
0636         execution::blocking_t
0637       >::value
0638     >
0639   >
0640 {
0641   static constexpr bool is_valid = true;
0642   static constexpr bool is_noexcept = true;
0643   typedef Blocking result_type;
0644 
0645   static constexpr result_type value() noexcept
0646   {
0647     return result_type();
0648   }
0649 };
0650 
0651 template <typename Executor, typename Blocking,
0652     typename InlineExceptionHandling, typename Property>
0653 struct query_static_constexpr_member<
0654     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0655     Property,
0656     enable_if_t<
0657       is_convertible<
0658         Property,
0659         execution::inline_exception_handling_t
0660       >::value
0661     >
0662   >
0663 {
0664   static constexpr bool is_valid = true;
0665   static constexpr bool is_noexcept = true;
0666   typedef InlineExceptionHandling result_type;
0667 
0668   static constexpr result_type value() noexcept
0669   {
0670     return result_type();
0671   }
0672 };
0673 
0674 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)
0675 
0676 #if !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0677 
0678 template <typename Executor, typename Blocking,
0679     typename InlineExceptionHandling, typename Property>
0680 struct query_member<
0681     inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0682     enable_if_t<
0683       can_query<const Executor&, Property>::value
0684         && !is_convertible<Property,
0685           execution::blocking_t>::value
0686         && !is_convertible<Property,
0687           execution::inline_exception_handling_t>::value
0688     >
0689   >
0690 {
0691   static constexpr bool is_valid = true;
0692   static constexpr bool is_noexcept =
0693     is_nothrow_query<Executor, Property>::value;
0694   typedef query_result_t<Executor, Property> result_type;
0695 };
0696 
0697 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)
0698 
0699 #if !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0700 
0701 template <typename Executor, typename Blocking,
0702     typename InlineExceptionHandling>
0703 struct require_member<
0704     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0705     execution::blocking_t::possibly_t
0706   >
0707 {
0708   static constexpr bool is_valid = true;
0709   static constexpr bool is_noexcept = true;
0710   typedef inline_or_executor<Executor, execution::blocking_t::possibly_t,
0711       InlineExceptionHandling> result_type;
0712 };
0713 
0714 template <typename Executor, typename Blocking,
0715     typename InlineExceptionHandling>
0716 struct require_member<
0717     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0718     execution::blocking_t::always_t
0719   >
0720 {
0721   static constexpr bool is_valid = true;
0722   static constexpr bool is_noexcept = true;
0723   typedef inline_or_executor<Executor, execution::blocking_t::always_t,
0724       InlineExceptionHandling> result_type;
0725 };
0726 
0727 template <typename Executor, typename Blocking,
0728     typename InlineExceptionHandling>
0729 struct require_member<
0730     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0731     execution::blocking_t::never_t
0732   >
0733 {
0734   static constexpr bool is_valid = true;
0735   static constexpr bool is_noexcept = true;
0736   typedef inline_or_executor<Executor, execution::blocking_t::never_t,
0737       InlineExceptionHandling> result_type;
0738 };
0739 
0740 template <typename Executor, typename Blocking,
0741     typename InlineExceptionHandling>
0742 struct require_member<
0743     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0744     execution::inline_exception_handling_t::propagate_t
0745   >
0746 {
0747   static constexpr bool is_valid = true;
0748   static constexpr bool is_noexcept = true;
0749   typedef inline_or_executor<Executor, Blocking,
0750       execution::inline_exception_handling_t::propagate_t> result_type;
0751 };
0752 
0753 template <typename Executor, typename Blocking,
0754     typename InlineExceptionHandling>
0755 struct require_member<
0756     inline_or_executor<Executor, Blocking, InlineExceptionHandling>,
0757     execution::inline_exception_handling_t::terminate_t
0758   >
0759 {
0760   static constexpr bool is_valid = true;
0761   static constexpr bool is_noexcept = true;
0762   typedef inline_or_executor<Executor, Blocking,
0763       execution::inline_exception_handling_t::terminate_t> result_type;
0764 };
0765 
0766 template <typename Executor, typename Blocking,
0767     typename InlineExceptionHandling, typename Property>
0768 struct require_member<
0769     inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0770     enable_if_t<
0771       can_require<const Executor&, Property>::value
0772         && !is_convertible<Property,
0773           execution::blocking_t>::value
0774         && !is_convertible<Property,
0775           execution::inline_exception_handling_t>::value
0776     >
0777   >
0778 {
0779   static constexpr bool is_valid = true;
0780   static constexpr bool is_noexcept =
0781     is_nothrow_require<const Executor&, Property>::value;
0782   typedef inline_or_executor<
0783       decay_t<require_result_t<const Executor&, Property>>,
0784         Blocking, InlineExceptionHandling> result_type;
0785 };
0786 
0787 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)
0788 
0789 #if !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
0790 
0791 template <typename Executor, typename Blocking,
0792     typename InlineExceptionHandling, typename Property>
0793 struct prefer_member<
0794     inline_or_executor<Executor, Blocking, InlineExceptionHandling>, Property,
0795     enable_if_t<
0796       can_prefer<const Executor&, Property>::value
0797         && !is_convertible<Property, execution::blocking_t::always_t>::value
0798     >
0799   >
0800 {
0801   static constexpr bool is_valid = true;
0802   static constexpr bool is_noexcept =
0803     is_nothrow_prefer<const Executor&, Property>::value;
0804   typedef inline_or_executor<
0805       decay_t<prefer_result_t<const Executor&, Property>>,
0806         Blocking, InlineExceptionHandling> result_type;
0807 };
0808 
0809 #endif // !defined(BOOST_ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)
0810 
0811 } // namespace traits
0812 
0813 #endif // !defined(GENERATING_DOCUMENTATION)
0814 
0815 } // namespace asio
0816 } // namespace boost
0817 
0818 #include <boost/asio/detail/pop_options.hpp>
0819 
0820 #endif // BOOST_ASIO_INLINE_OR_EXECUTOR_HPP