Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/asio/bind_allocator.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 //
0002 // bind_allocator.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_BIND_ALLOCATOR_HPP
0012 #define BOOST_ASIO_BIND_ALLOCATOR_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/associated_allocator.hpp>
0020 #include <boost/asio/associated_executor.hpp>
0021 #include <boost/asio/associator.hpp>
0022 #include <boost/asio/async_result.hpp>
0023 #include <boost/asio/detail/initiation_base.hpp>
0024 #include <boost/asio/detail/type_traits.hpp>
0025 
0026 #include <boost/asio/detail/push_options.hpp>
0027 
0028 namespace boost {
0029 namespace asio {
0030 namespace detail {
0031 
0032 // Helper to automatically define nested typedef result_type.
0033 
0034 template <typename T, typename = void>
0035 struct allocator_binder_result_type
0036 {
0037 protected:
0038   typedef void result_type_or_void;
0039 };
0040 
0041 template <typename T>
0042 struct allocator_binder_result_type<T, void_t<typename T::result_type>>
0043 {
0044   typedef typename T::result_type result_type;
0045 protected:
0046   typedef result_type result_type_or_void;
0047 };
0048 
0049 template <typename R>
0050 struct allocator_binder_result_type<R(*)()>
0051 {
0052   typedef R result_type;
0053 protected:
0054   typedef result_type result_type_or_void;
0055 };
0056 
0057 template <typename R>
0058 struct allocator_binder_result_type<R(&)()>
0059 {
0060   typedef R result_type;
0061 protected:
0062   typedef result_type result_type_or_void;
0063 };
0064 
0065 template <typename R, typename A1>
0066 struct allocator_binder_result_type<R(*)(A1)>
0067 {
0068   typedef R result_type;
0069 protected:
0070   typedef result_type result_type_or_void;
0071 };
0072 
0073 template <typename R, typename A1>
0074 struct allocator_binder_result_type<R(&)(A1)>
0075 {
0076   typedef R result_type;
0077 protected:
0078   typedef result_type result_type_or_void;
0079 };
0080 
0081 template <typename R, typename A1, typename A2>
0082 struct allocator_binder_result_type<R(*)(A1, A2)>
0083 {
0084   typedef R result_type;
0085 protected:
0086   typedef result_type result_type_or_void;
0087 };
0088 
0089 template <typename R, typename A1, typename A2>
0090 struct allocator_binder_result_type<R(&)(A1, A2)>
0091 {
0092   typedef R result_type;
0093 protected:
0094   typedef result_type result_type_or_void;
0095 };
0096 
0097 // Helper to automatically define nested typedef argument_type.
0098 
0099 template <typename T, typename = void>
0100 struct allocator_binder_argument_type {};
0101 
0102 template <typename T>
0103 struct allocator_binder_argument_type<T, void_t<typename T::argument_type>>
0104 {
0105   typedef typename T::argument_type argument_type;
0106 };
0107 
0108 template <typename R, typename A1>
0109 struct allocator_binder_argument_type<R(*)(A1)>
0110 {
0111   typedef A1 argument_type;
0112 };
0113 
0114 template <typename R, typename A1>
0115 struct allocator_binder_argument_type<R(&)(A1)>
0116 {
0117   typedef A1 argument_type;
0118 };
0119 
0120 // Helper to automatically define nested typedefs first_argument_type and
0121 // second_argument_type.
0122 
0123 template <typename T, typename = void>
0124 struct allocator_binder_argument_types {};
0125 
0126 template <typename T>
0127 struct allocator_binder_argument_types<T,
0128     void_t<typename T::first_argument_type>>
0129 {
0130   typedef typename T::first_argument_type first_argument_type;
0131   typedef typename T::second_argument_type second_argument_type;
0132 };
0133 
0134 template <typename R, typename A1, typename A2>
0135 struct allocator_binder_argument_type<R(*)(A1, A2)>
0136 {
0137   typedef A1 first_argument_type;
0138   typedef A2 second_argument_type;
0139 };
0140 
0141 template <typename R, typename A1, typename A2>
0142 struct allocator_binder_argument_type<R(&)(A1, A2)>
0143 {
0144   typedef A1 first_argument_type;
0145   typedef A2 second_argument_type;
0146 };
0147 
0148 } // namespace detail
0149 
0150 /// A call wrapper type to bind an allocator of type @c Allocator
0151 /// to an object of type @c T.
0152 template <typename T, typename Allocator>
0153 class allocator_binder
0154 #if !defined(GENERATING_DOCUMENTATION)
0155   : public detail::allocator_binder_result_type<T>,
0156     public detail::allocator_binder_argument_type<T>,
0157     public detail::allocator_binder_argument_types<T>
0158 #endif // !defined(GENERATING_DOCUMENTATION)
0159 {
0160 public:
0161   /// The type of the target object.
0162   typedef T target_type;
0163 
0164   /// The type of the associated allocator.
0165   typedef Allocator allocator_type;
0166 
0167 #if defined(GENERATING_DOCUMENTATION)
0168   /// The return type if a function.
0169   /**
0170    * The type of @c result_type is based on the type @c T of the wrapper's
0171    * target object:
0172    *
0173    * @li if @c T is a pointer to function type, @c result_type is a synonym for
0174    * the return type of @c T;
0175    *
0176    * @li if @c T is a class type with a member type @c result_type, then @c
0177    * result_type is a synonym for @c T::result_type;
0178    *
0179    * @li otherwise @c result_type is not defined.
0180    */
0181   typedef see_below result_type;
0182 
0183   /// The type of the function's argument.
0184   /**
0185    * The type of @c argument_type is based on the type @c T of the wrapper's
0186    * target object:
0187    *
0188    * @li if @c T is a pointer to a function type accepting a single argument,
0189    * @c argument_type is a synonym for the return type of @c T;
0190    *
0191    * @li if @c T is a class type with a member type @c argument_type, then @c
0192    * argument_type is a synonym for @c T::argument_type;
0193    *
0194    * @li otherwise @c argument_type is not defined.
0195    */
0196   typedef see_below argument_type;
0197 
0198   /// The type of the function's first argument.
0199   /**
0200    * The type of @c first_argument_type is based on the type @c T of the
0201    * wrapper's target object:
0202    *
0203    * @li if @c T is a pointer to a function type accepting two arguments, @c
0204    * first_argument_type is a synonym for the return type of @c T;
0205    *
0206    * @li if @c T is a class type with a member type @c first_argument_type,
0207    * then @c first_argument_type is a synonym for @c T::first_argument_type;
0208    *
0209    * @li otherwise @c first_argument_type is not defined.
0210    */
0211   typedef see_below first_argument_type;
0212 
0213   /// The type of the function's second argument.
0214   /**
0215    * The type of @c second_argument_type is based on the type @c T of the
0216    * wrapper's target object:
0217    *
0218    * @li if @c T is a pointer to a function type accepting two arguments, @c
0219    * second_argument_type is a synonym for the return type of @c T;
0220    *
0221    * @li if @c T is a class type with a member type @c first_argument_type,
0222    * then @c second_argument_type is a synonym for @c T::second_argument_type;
0223    *
0224    * @li otherwise @c second_argument_type is not defined.
0225    */
0226   typedef see_below second_argument_type;
0227 #endif // defined(GENERATING_DOCUMENTATION)
0228 
0229   /// Construct an allocator wrapper for the specified object.
0230   /**
0231    * This constructor is only valid if the type @c T is constructible from type
0232    * @c U.
0233    */
0234   template <typename U>
0235   allocator_binder(const allocator_type& s, U&& u)
0236     : allocator_(s),
0237       target_(static_cast<U&&>(u))
0238   {
0239   }
0240 
0241   /// Copy constructor.
0242   allocator_binder(const allocator_binder& other)
0243     : allocator_(other.get_allocator()),
0244       target_(other.get())
0245   {
0246   }
0247 
0248   /// Construct a copy, but specify a different allocator.
0249   allocator_binder(const allocator_type& s, const allocator_binder& other)
0250     : allocator_(s),
0251       target_(other.get())
0252   {
0253   }
0254 
0255   /// Construct a copy of a different allocator wrapper type.
0256   /**
0257    * This constructor is only valid if the @c Allocator type is
0258    * constructible from type @c OtherAllocator, and the type @c T is
0259    * constructible from type @c U.
0260    */
0261   template <typename U, typename OtherAllocator>
0262   allocator_binder(const allocator_binder<U, OtherAllocator>& other,
0263       constraint_t<is_constructible<Allocator, OtherAllocator>::value> = 0,
0264       constraint_t<is_constructible<T, U>::value> = 0)
0265     : allocator_(other.get_allocator()),
0266       target_(other.get())
0267   {
0268   }
0269 
0270   /// Construct a copy of a different allocator wrapper type, but
0271   /// specify a different allocator.
0272   /**
0273    * This constructor is only valid if the type @c T is constructible from type
0274    * @c U.
0275    */
0276   template <typename U, typename OtherAllocator>
0277   allocator_binder(const allocator_type& s,
0278       const allocator_binder<U, OtherAllocator>& other,
0279       constraint_t<is_constructible<T, U>::value> = 0)
0280     : allocator_(s),
0281       target_(other.get())
0282   {
0283   }
0284 
0285   /// Move constructor.
0286   allocator_binder(allocator_binder&& other)
0287     : allocator_(static_cast<allocator_type&&>(
0288           other.get_allocator())),
0289       target_(static_cast<T&&>(other.get()))
0290   {
0291   }
0292 
0293   /// Move construct the target object, but specify a different allocator.
0294   allocator_binder(const allocator_type& s,
0295       allocator_binder&& other)
0296     : allocator_(s),
0297       target_(static_cast<T&&>(other.get()))
0298   {
0299   }
0300 
0301   /// Move construct from a different allocator wrapper type.
0302   template <typename U, typename OtherAllocator>
0303   allocator_binder(
0304       allocator_binder<U, OtherAllocator>&& other,
0305       constraint_t<is_constructible<Allocator, OtherAllocator>::value> = 0,
0306       constraint_t<is_constructible<T, U>::value> = 0)
0307     : allocator_(static_cast<OtherAllocator&&>(
0308           other.get_allocator())),
0309       target_(static_cast<U&&>(other.get()))
0310   {
0311   }
0312 
0313   /// Move construct from a different allocator wrapper type, but
0314   /// specify a different allocator.
0315   template <typename U, typename OtherAllocator>
0316   allocator_binder(const allocator_type& s,
0317       allocator_binder<U, OtherAllocator>&& other,
0318       constraint_t<is_constructible<T, U>::value> = 0)
0319     : allocator_(s),
0320       target_(static_cast<U&&>(other.get()))
0321   {
0322   }
0323 
0324   /// Destructor.
0325   ~allocator_binder()
0326   {
0327   }
0328 
0329   /// Obtain a reference to the target object.
0330   target_type& get() noexcept
0331   {
0332     return target_;
0333   }
0334 
0335   /// Obtain a reference to the target object.
0336   const target_type& get() const noexcept
0337   {
0338     return target_;
0339   }
0340 
0341   /// Obtain the associated allocator.
0342   allocator_type get_allocator() const noexcept
0343   {
0344     return allocator_;
0345   }
0346 
0347   /// Forwarding function call operator.
0348   template <typename... Args>
0349   result_of_t<T(Args...)> operator()(Args&&... args) &
0350   {
0351     return target_(static_cast<Args&&>(args)...);
0352   }
0353 
0354   /// Forwarding function call operator.
0355   template <typename... Args>
0356   result_of_t<T(Args...)> operator()(Args&&... args) &&
0357   {
0358     return static_cast<T&&>(target_)(static_cast<Args&&>(args)...);
0359   }
0360 
0361   /// Forwarding function call operator.
0362   template <typename... Args>
0363   result_of_t<T(Args...)> operator()(Args&&... args) const&
0364   {
0365     return target_(static_cast<Args&&>(args)...);
0366   }
0367 
0368 private:
0369   Allocator allocator_;
0370   T target_;
0371 };
0372 
0373 /// A function object type that adapts a @ref completion_token to specify that
0374 /// the completion handler should have the supplied allocator as its associated
0375 /// allocator.
0376 /**
0377  * May also be used directly as a completion token, in which case it adapts the
0378  * asynchronous operation's default completion token (or boost::asio::deferred
0379  * if no default is available).
0380  */
0381 template <typename Allocator>
0382 struct partial_allocator_binder
0383 {
0384   /// Constructor that specifies associated allocator.
0385   explicit partial_allocator_binder(const Allocator& ex)
0386     : allocator_(ex)
0387   {
0388   }
0389 
0390   /// Adapt a @ref completion_token to specify that the completion handler
0391   /// should have the allocator as its associated allocator.
0392   template <typename CompletionToken>
0393   BOOST_ASIO_NODISCARD inline
0394   constexpr allocator_binder<decay_t<CompletionToken>, Allocator>
0395   operator()(CompletionToken&& completion_token) const
0396   {
0397     return allocator_binder<decay_t<CompletionToken>, Allocator>(
0398         allocator_, static_cast<CompletionToken&&>(completion_token));
0399   }
0400 
0401 //private:
0402   Allocator allocator_;
0403 };
0404 
0405 /// Create a partial completion token that associates an allocator.
0406 template <typename Allocator>
0407 BOOST_ASIO_NODISCARD inline partial_allocator_binder<Allocator>
0408 bind_allocator(const Allocator& ex)
0409 {
0410   return partial_allocator_binder<Allocator>(ex);
0411 }
0412 
0413 /// Associate an object of type @c T with an allocator of type
0414 /// @c Allocator.
0415 template <typename Allocator, typename T>
0416 BOOST_ASIO_NODISCARD inline allocator_binder<decay_t<T>, Allocator>
0417 bind_allocator(const Allocator& s, T&& t)
0418 {
0419   return allocator_binder<decay_t<T>, Allocator>(s, static_cast<T&&>(t));
0420 }
0421 
0422 #if !defined(GENERATING_DOCUMENTATION)
0423 
0424 namespace detail {
0425 
0426 template <typename TargetAsyncResult, typename Allocator, typename = void>
0427 class allocator_binder_completion_handler_async_result
0428 {
0429 public:
0430   template <typename T>
0431   explicit allocator_binder_completion_handler_async_result(T&)
0432   {
0433   }
0434 };
0435 
0436 template <typename TargetAsyncResult, typename Allocator>
0437 class allocator_binder_completion_handler_async_result<
0438     TargetAsyncResult, Allocator,
0439     void_t<typename TargetAsyncResult::completion_handler_type>>
0440 {
0441 private:
0442   TargetAsyncResult target_;
0443 
0444 public:
0445   typedef allocator_binder<
0446     typename TargetAsyncResult::completion_handler_type, Allocator>
0447       completion_handler_type;
0448 
0449   explicit allocator_binder_completion_handler_async_result(
0450       typename TargetAsyncResult::completion_handler_type& handler)
0451     : target_(handler)
0452   {
0453   }
0454 
0455   auto get() -> decltype(target_.get())
0456   {
0457     return target_.get();
0458   }
0459 };
0460 
0461 template <typename TargetAsyncResult, typename = void>
0462 struct allocator_binder_async_result_return_type
0463 {
0464 };
0465 
0466 template <typename TargetAsyncResult>
0467 struct allocator_binder_async_result_return_type<
0468     TargetAsyncResult, void_type<typename TargetAsyncResult::return_type>>
0469 {
0470   typedef typename TargetAsyncResult::return_type return_type;
0471 };
0472 
0473 } // namespace detail
0474 
0475 template <typename T, typename Allocator, typename Signature>
0476 class async_result<allocator_binder<T, Allocator>, Signature> :
0477   public detail::allocator_binder_completion_handler_async_result<
0478       async_result<T, Signature>, Allocator>,
0479   public detail::allocator_binder_async_result_return_type<
0480       async_result<T, Signature>>
0481 {
0482 public:
0483   explicit async_result(allocator_binder<T, Allocator>& b)
0484     : detail::allocator_binder_completion_handler_async_result<
0485         async_result<T, Signature>, Allocator>(b.get())
0486   {
0487   }
0488 
0489   template <typename Initiation>
0490   struct init_wrapper : detail::initiation_base<Initiation>
0491   {
0492     using detail::initiation_base<Initiation>::initiation_base;
0493 
0494     template <typename Handler, typename... Args>
0495     void operator()(Handler&& handler, const Allocator& a, Args&&... args) &&
0496     {
0497       static_cast<Initiation&&>(*this)(
0498           allocator_binder<decay_t<Handler>, Allocator>(
0499               a, static_cast<Handler&&>(handler)),
0500           static_cast<Args&&>(args)...);
0501     }
0502 
0503     template <typename Handler, typename... Args>
0504     void operator()(Handler&& handler,
0505         const Allocator& a, Args&&... args) const &
0506     {
0507       static_cast<const Initiation&>(*this)(
0508           allocator_binder<decay_t<Handler>, Allocator>(
0509               a, static_cast<Handler&&>(handler)),
0510           static_cast<Args&&>(args)...);
0511     }
0512   };
0513 
0514   template <typename Initiation, typename RawCompletionToken, typename... Args>
0515   static auto initiate(Initiation&& initiation,
0516       RawCompletionToken&& token, Args&&... args)
0517     -> decltype(
0518       async_initiate<
0519         conditional_t<
0520           is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0521         Signature>(
0522         declval<init_wrapper<decay_t<Initiation>>>(),
0523         token.get(), token.get_allocator(), static_cast<Args&&>(args)...))
0524   {
0525     return async_initiate<
0526       conditional_t<
0527         is_const<remove_reference_t<RawCompletionToken>>::value, const T, T>,
0528       Signature>(
0529         init_wrapper<decay_t<Initiation>>(
0530           static_cast<Initiation&&>(initiation)),
0531         token.get(), token.get_allocator(), static_cast<Args&&>(args)...);
0532   }
0533 
0534 private:
0535   async_result(const async_result&) = delete;
0536   async_result& operator=(const async_result&) = delete;
0537 
0538   async_result<T, Signature> target_;
0539 };
0540 
0541 template <typename Allocator, typename... Signatures>
0542 struct async_result<partial_allocator_binder<Allocator>, Signatures...>
0543 {
0544   template <typename Initiation, typename RawCompletionToken, typename... Args>
0545   static auto initiate(Initiation&& initiation,
0546       RawCompletionToken&& token, Args&&... args)
0547     -> decltype(
0548       async_initiate<Signatures...>(
0549         static_cast<Initiation&&>(initiation),
0550         allocator_binder<
0551           default_completion_token_t<associated_executor_t<Initiation>>,
0552           Allocator>(token.allocator_,
0553             default_completion_token_t<associated_executor_t<Initiation>>{}),
0554         static_cast<Args&&>(args)...))
0555   {
0556     return async_initiate<Signatures...>(
0557         static_cast<Initiation&&>(initiation),
0558         allocator_binder<
0559           default_completion_token_t<associated_executor_t<Initiation>>,
0560           Allocator>(token.allocator_,
0561             default_completion_token_t<associated_executor_t<Initiation>>{}),
0562         static_cast<Args&&>(args)...);
0563   }
0564 };
0565 
0566 template <template <typename, typename> class Associator,
0567     typename T, typename Allocator, typename DefaultCandidate>
0568 struct associator<Associator, allocator_binder<T, Allocator>, DefaultCandidate>
0569   : Associator<T, DefaultCandidate>
0570 {
0571   static typename Associator<T, DefaultCandidate>::type get(
0572       const allocator_binder<T, Allocator>& b) noexcept
0573   {
0574     return Associator<T, DefaultCandidate>::get(b.get());
0575   }
0576 
0577   static auto get(const allocator_binder<T, Allocator>& b,
0578       const DefaultCandidate& c) noexcept
0579     -> decltype(Associator<T, DefaultCandidate>::get(b.get(), c))
0580   {
0581     return Associator<T, DefaultCandidate>::get(b.get(), c);
0582   }
0583 };
0584 
0585 template <typename T, typename Allocator, typename Allocator1>
0586 struct associated_allocator<allocator_binder<T, Allocator>, Allocator1>
0587 {
0588   typedef Allocator type;
0589 
0590   static auto get(const allocator_binder<T, Allocator>& b,
0591       const Allocator1& = Allocator1()) noexcept
0592     -> decltype(b.get_allocator())
0593   {
0594     return b.get_allocator();
0595   }
0596 };
0597 
0598 #endif // !defined(GENERATING_DOCUMENTATION)
0599 
0600 } // namespace asio
0601 } // namespace boost
0602 
0603 #include <boost/asio/detail/pop_options.hpp>
0604 
0605 #endif // BOOST_ASIO_BIND_ALLOCATOR_HPP