bind_allocator.hpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. //
  2. // bind_allocator.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 BOOST_ASIO_BIND_ALLOCATOR_HPP
  11. #define BOOST_ASIO_BIND_ALLOCATOR_HPP
  12. #if defined(_MSC_VER) && (_MSC_VER >= 1200)
  13. # pragma once
  14. #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
  15. #include <boost/asio/detail/config.hpp>
  16. #include <boost/asio/detail/type_traits.hpp>
  17. #include <boost/asio/detail/variadic_templates.hpp>
  18. #include <boost/asio/associated_allocator.hpp>
  19. #include <boost/asio/associator.hpp>
  20. #include <boost/asio/async_result.hpp>
  21. #include <boost/asio/detail/push_options.hpp>
  22. namespace boost {
  23. namespace asio {
  24. namespace detail {
  25. // Helper to automatically define nested typedef result_type.
  26. template <typename T, typename = void>
  27. struct allocator_binder_result_type
  28. {
  29. protected:
  30. typedef void result_type_or_void;
  31. };
  32. template <typename T>
  33. struct allocator_binder_result_type<T,
  34. typename void_type<typename T::result_type>::type>
  35. {
  36. typedef typename T::result_type result_type;
  37. protected:
  38. typedef result_type result_type_or_void;
  39. };
  40. template <typename R>
  41. struct allocator_binder_result_type<R(*)()>
  42. {
  43. typedef R result_type;
  44. protected:
  45. typedef result_type result_type_or_void;
  46. };
  47. template <typename R>
  48. struct allocator_binder_result_type<R(&)()>
  49. {
  50. typedef R result_type;
  51. protected:
  52. typedef result_type result_type_or_void;
  53. };
  54. template <typename R, typename A1>
  55. struct allocator_binder_result_type<R(*)(A1)>
  56. {
  57. typedef R result_type;
  58. protected:
  59. typedef result_type result_type_or_void;
  60. };
  61. template <typename R, typename A1>
  62. struct allocator_binder_result_type<R(&)(A1)>
  63. {
  64. typedef R result_type;
  65. protected:
  66. typedef result_type result_type_or_void;
  67. };
  68. template <typename R, typename A1, typename A2>
  69. struct allocator_binder_result_type<R(*)(A1, A2)>
  70. {
  71. typedef R result_type;
  72. protected:
  73. typedef result_type result_type_or_void;
  74. };
  75. template <typename R, typename A1, typename A2>
  76. struct allocator_binder_result_type<R(&)(A1, A2)>
  77. {
  78. typedef R result_type;
  79. protected:
  80. typedef result_type result_type_or_void;
  81. };
  82. // Helper to automatically define nested typedef argument_type.
  83. template <typename T, typename = void>
  84. struct allocator_binder_argument_type {};
  85. template <typename T>
  86. struct allocator_binder_argument_type<T,
  87. typename void_type<typename T::argument_type>::type>
  88. {
  89. typedef typename T::argument_type argument_type;
  90. };
  91. template <typename R, typename A1>
  92. struct allocator_binder_argument_type<R(*)(A1)>
  93. {
  94. typedef A1 argument_type;
  95. };
  96. template <typename R, typename A1>
  97. struct allocator_binder_argument_type<R(&)(A1)>
  98. {
  99. typedef A1 argument_type;
  100. };
  101. // Helper to automatically define nested typedefs first_argument_type and
  102. // second_argument_type.
  103. template <typename T, typename = void>
  104. struct allocator_binder_argument_types {};
  105. template <typename T>
  106. struct allocator_binder_argument_types<T,
  107. typename void_type<typename T::first_argument_type>::type>
  108. {
  109. typedef typename T::first_argument_type first_argument_type;
  110. typedef typename T::second_argument_type second_argument_type;
  111. };
  112. template <typename R, typename A1, typename A2>
  113. struct allocator_binder_argument_type<R(*)(A1, A2)>
  114. {
  115. typedef A1 first_argument_type;
  116. typedef A2 second_argument_type;
  117. };
  118. template <typename R, typename A1, typename A2>
  119. struct allocator_binder_argument_type<R(&)(A1, A2)>
  120. {
  121. typedef A1 first_argument_type;
  122. typedef A2 second_argument_type;
  123. };
  124. // Helper to enable SFINAE on zero-argument operator() below.
  125. template <typename T, typename = void>
  126. struct allocator_binder_result_of0
  127. {
  128. typedef void type;
  129. };
  130. template <typename T>
  131. struct allocator_binder_result_of0<T,
  132. typename void_type<typename result_of<T()>::type>::type>
  133. {
  134. typedef typename result_of<T()>::type type;
  135. };
  136. } // namespace detail
  137. /// A call wrapper type to bind an allocator of type @c Allocator
  138. /// to an object of type @c T.
  139. template <typename T, typename Allocator>
  140. class allocator_binder
  141. #if !defined(GENERATING_DOCUMENTATION)
  142. : public detail::allocator_binder_result_type<T>,
  143. public detail::allocator_binder_argument_type<T>,
  144. public detail::allocator_binder_argument_types<T>
  145. #endif // !defined(GENERATING_DOCUMENTATION)
  146. {
  147. public:
  148. /// The type of the target object.
  149. typedef T target_type;
  150. /// The type of the associated allocator.
  151. typedef Allocator allocator_type;
  152. #if defined(GENERATING_DOCUMENTATION)
  153. /// The return type if a function.
  154. /**
  155. * The type of @c result_type is based on the type @c T of the wrapper's
  156. * target object:
  157. *
  158. * @li if @c T is a pointer to function type, @c result_type is a synonym for
  159. * the return type of @c T;
  160. *
  161. * @li if @c T is a class type with a member type @c result_type, then @c
  162. * result_type is a synonym for @c T::result_type;
  163. *
  164. * @li otherwise @c result_type is not defined.
  165. */
  166. typedef see_below result_type;
  167. /// The type of the function's argument.
  168. /**
  169. * The type of @c argument_type is based on the type @c T of the wrapper's
  170. * target object:
  171. *
  172. * @li if @c T is a pointer to a function type accepting a single argument,
  173. * @c argument_type is a synonym for the return type of @c T;
  174. *
  175. * @li if @c T is a class type with a member type @c argument_type, then @c
  176. * argument_type is a synonym for @c T::argument_type;
  177. *
  178. * @li otherwise @c argument_type is not defined.
  179. */
  180. typedef see_below argument_type;
  181. /// The type of the function's first argument.
  182. /**
  183. * The type of @c first_argument_type is based on the type @c T of the
  184. * wrapper's target object:
  185. *
  186. * @li if @c T is a pointer to a function type accepting two arguments, @c
  187. * first_argument_type is a synonym for the return type of @c T;
  188. *
  189. * @li if @c T is a class type with a member type @c first_argument_type,
  190. * then @c first_argument_type is a synonym for @c T::first_argument_type;
  191. *
  192. * @li otherwise @c first_argument_type is not defined.
  193. */
  194. typedef see_below first_argument_type;
  195. /// The type of the function's second argument.
  196. /**
  197. * The type of @c second_argument_type is based on the type @c T of the
  198. * wrapper's target object:
  199. *
  200. * @li if @c T is a pointer to a function type accepting two arguments, @c
  201. * second_argument_type is a synonym for the return type of @c T;
  202. *
  203. * @li if @c T is a class type with a member type @c first_argument_type,
  204. * then @c second_argument_type is a synonym for @c T::second_argument_type;
  205. *
  206. * @li otherwise @c second_argument_type is not defined.
  207. */
  208. typedef see_below second_argument_type;
  209. #endif // defined(GENERATING_DOCUMENTATION)
  210. /// Construct an allocator wrapper for the specified object.
  211. /**
  212. * This constructor is only valid if the type @c T is constructible from type
  213. * @c U.
  214. */
  215. template <typename U>
  216. allocator_binder(const allocator_type& s,
  217. BOOST_ASIO_MOVE_ARG(U) u)
  218. : allocator_(s),
  219. target_(BOOST_ASIO_MOVE_CAST(U)(u))
  220. {
  221. }
  222. /// Copy constructor.
  223. allocator_binder(const allocator_binder& other)
  224. : allocator_(other.get_allocator()),
  225. target_(other.get())
  226. {
  227. }
  228. /// Construct a copy, but specify a different allocator.
  229. allocator_binder(const allocator_type& s,
  230. const allocator_binder& other)
  231. : allocator_(s),
  232. target_(other.get())
  233. {
  234. }
  235. /// Construct a copy of a different allocator wrapper type.
  236. /**
  237. * This constructor is only valid if the @c Allocator type is
  238. * constructible from type @c OtherAllocator, and the type @c T is
  239. * constructible from type @c U.
  240. */
  241. template <typename U, typename OtherAllocator>
  242. allocator_binder(
  243. const allocator_binder<U, OtherAllocator>& other)
  244. : allocator_(other.get_allocator()),
  245. target_(other.get())
  246. {
  247. }
  248. /// Construct a copy of a different allocator wrapper type, but
  249. /// specify a different allocator.
  250. /**
  251. * This constructor is only valid if the type @c T is constructible from type
  252. * @c U.
  253. */
  254. template <typename U, typename OtherAllocator>
  255. allocator_binder(const allocator_type& s,
  256. const allocator_binder<U, OtherAllocator>& other)
  257. : allocator_(s),
  258. target_(other.get())
  259. {
  260. }
  261. #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  262. /// Move constructor.
  263. allocator_binder(allocator_binder&& other)
  264. : allocator_(BOOST_ASIO_MOVE_CAST(allocator_type)(
  265. other.get_allocator())),
  266. target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
  267. {
  268. }
  269. /// Move construct the target object, but specify a different allocator.
  270. allocator_binder(const allocator_type& s,
  271. allocator_binder&& other)
  272. : allocator_(s),
  273. target_(BOOST_ASIO_MOVE_CAST(T)(other.get()))
  274. {
  275. }
  276. /// Move construct from a different allocator wrapper type.
  277. template <typename U, typename OtherAllocator>
  278. allocator_binder(
  279. allocator_binder<U, OtherAllocator>&& other)
  280. : allocator_(BOOST_ASIO_MOVE_CAST(OtherAllocator)(
  281. other.get_allocator())),
  282. target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
  283. {
  284. }
  285. /// Move construct from a different allocator wrapper type, but
  286. /// specify a different allocator.
  287. template <typename U, typename OtherAllocator>
  288. allocator_binder(const allocator_type& s,
  289. allocator_binder<U, OtherAllocator>&& other)
  290. : allocator_(s),
  291. target_(BOOST_ASIO_MOVE_CAST(U)(other.get()))
  292. {
  293. }
  294. #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
  295. /// Destructor.
  296. ~allocator_binder()
  297. {
  298. }
  299. /// Obtain a reference to the target object.
  300. target_type& get() BOOST_ASIO_NOEXCEPT
  301. {
  302. return target_;
  303. }
  304. /// Obtain a reference to the target object.
  305. const target_type& get() const BOOST_ASIO_NOEXCEPT
  306. {
  307. return target_;
  308. }
  309. /// Obtain the associated allocator.
  310. allocator_type get_allocator() const BOOST_ASIO_NOEXCEPT
  311. {
  312. return allocator_;
  313. }
  314. #if defined(GENERATING_DOCUMENTATION)
  315. template <typename... Args> auto operator()(Args&& ...);
  316. template <typename... Args> auto operator()(Args&& ...) const;
  317. #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  318. /// Forwarding function call operator.
  319. template <typename... Args>
  320. typename result_of<T(Args...)>::type operator()(
  321. BOOST_ASIO_MOVE_ARG(Args)... args)
  322. {
  323. return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
  324. }
  325. /// Forwarding function call operator.
  326. template <typename... Args>
  327. typename result_of<T(Args...)>::type operator()(
  328. BOOST_ASIO_MOVE_ARG(Args)... args) const
  329. {
  330. return target_(BOOST_ASIO_MOVE_CAST(Args)(args)...);
  331. }
  332. #elif defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  333. typename detail::allocator_binder_result_of0<T>::type operator()()
  334. {
  335. return target_();
  336. }
  337. typename detail::allocator_binder_result_of0<T>::type
  338. operator()() const
  339. {
  340. return target_();
  341. }
  342. #define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
  343. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  344. typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
  345. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  346. { \
  347. return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  348. } \
  349. \
  350. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  351. typename result_of<T(BOOST_ASIO_VARIADIC_TARGS(n))>::type operator()( \
  352. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  353. { \
  354. return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  355. } \
  356. /**/
  357. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
  358. #undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
  359. #else // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  360. typedef typename detail::allocator_binder_result_type<
  361. T>::result_type_or_void result_type_or_void;
  362. result_type_or_void operator()()
  363. {
  364. return target_();
  365. }
  366. result_type_or_void operator()() const
  367. {
  368. return target_();
  369. }
  370. #define BOOST_ASIO_PRIVATE_BINDER_CALL_DEF(n) \
  371. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  372. result_type_or_void operator()( \
  373. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  374. { \
  375. return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  376. } \
  377. \
  378. template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  379. result_type_or_void operator()( \
  380. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  381. { \
  382. return target_(BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  383. } \
  384. /**/
  385. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_BINDER_CALL_DEF)
  386. #undef BOOST_ASIO_PRIVATE_BINDER_CALL_DEF
  387. #endif // defined(BOOST_ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)
  388. private:
  389. Allocator allocator_;
  390. T target_;
  391. };
  392. /// Associate an object of type @c T with an allocator of type
  393. /// @c Allocator.
  394. template <typename Allocator, typename T>
  395. BOOST_ASIO_NODISCARD inline allocator_binder<typename decay<T>::type, Allocator>
  396. bind_allocator(const Allocator& s, BOOST_ASIO_MOVE_ARG(T) t)
  397. {
  398. return allocator_binder<
  399. typename decay<T>::type, Allocator>(
  400. s, BOOST_ASIO_MOVE_CAST(T)(t));
  401. }
  402. #if !defined(GENERATING_DOCUMENTATION)
  403. namespace detail {
  404. template <typename TargetAsyncResult,
  405. typename Allocator, typename = void>
  406. struct allocator_binder_async_result_completion_handler_type
  407. {
  408. };
  409. template <typename TargetAsyncResult, typename Allocator>
  410. struct allocator_binder_async_result_completion_handler_type<
  411. TargetAsyncResult, Allocator,
  412. typename void_type<
  413. typename TargetAsyncResult::completion_handler_type
  414. >::type>
  415. {
  416. typedef allocator_binder<
  417. typename TargetAsyncResult::completion_handler_type, Allocator>
  418. completion_handler_type;
  419. };
  420. template <typename TargetAsyncResult, typename = void>
  421. struct allocator_binder_async_result_return_type
  422. {
  423. };
  424. template <typename TargetAsyncResult>
  425. struct allocator_binder_async_result_return_type<
  426. TargetAsyncResult,
  427. typename void_type<
  428. typename TargetAsyncResult::return_type
  429. >::type>
  430. {
  431. typedef typename TargetAsyncResult::return_type return_type;
  432. };
  433. } // namespace detail
  434. template <typename T, typename Allocator, typename Signature>
  435. class async_result<allocator_binder<T, Allocator>, Signature> :
  436. public detail::allocator_binder_async_result_completion_handler_type<
  437. async_result<T, Signature>, Allocator>,
  438. public detail::allocator_binder_async_result_return_type<
  439. async_result<T, Signature> >
  440. {
  441. public:
  442. explicit async_result(allocator_binder<T, Allocator>& b)
  443. : target_(b.get())
  444. {
  445. }
  446. typename async_result<T, Signature>::return_type get()
  447. {
  448. return target_.get();
  449. }
  450. template <typename Initiation>
  451. struct init_wrapper
  452. {
  453. template <typename Init>
  454. init_wrapper(const Allocator& allocator, BOOST_ASIO_MOVE_ARG(Init) init)
  455. : allocator_(allocator),
  456. initiation_(BOOST_ASIO_MOVE_CAST(Init)(init))
  457. {
  458. }
  459. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  460. template <typename Handler, typename... Args>
  461. void operator()(
  462. BOOST_ASIO_MOVE_ARG(Handler) handler,
  463. BOOST_ASIO_MOVE_ARG(Args)... args)
  464. {
  465. BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
  466. allocator_binder<
  467. typename decay<Handler>::type, Allocator>(
  468. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
  469. BOOST_ASIO_MOVE_CAST(Args)(args)...);
  470. }
  471. template <typename Handler, typename... Args>
  472. void operator()(
  473. BOOST_ASIO_MOVE_ARG(Handler) handler,
  474. BOOST_ASIO_MOVE_ARG(Args)... args) const
  475. {
  476. initiation_(
  477. allocator_binder<
  478. typename decay<Handler>::type, Allocator>(
  479. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)),
  480. BOOST_ASIO_MOVE_CAST(Args)(args)...);
  481. }
  482. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  483. template <typename Handler>
  484. void operator()(
  485. BOOST_ASIO_MOVE_ARG(Handler) handler)
  486. {
  487. BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)(
  488. allocator_binder<
  489. typename decay<Handler>::type, Allocator>(
  490. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
  491. }
  492. template <typename Handler>
  493. void operator()(
  494. BOOST_ASIO_MOVE_ARG(Handler) handler) const
  495. {
  496. initiation_(
  497. allocator_binder<
  498. typename decay<Handler>::type, Allocator>(
  499. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)));
  500. }
  501. #define BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \
  502. template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  503. void operator()( \
  504. BOOST_ASIO_MOVE_ARG(Handler) handler, \
  505. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  506. { \
  507. BOOST_ASIO_MOVE_CAST(Initiation)(initiation_)( \
  508. allocator_binder< \
  509. typename decay<Handler>::type, Allocator>( \
  510. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
  511. BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  512. } \
  513. \
  514. template <typename Handler, BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  515. void operator()( \
  516. BOOST_ASIO_MOVE_ARG(Handler) handler, \
  517. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) const \
  518. { \
  519. initiation_( \
  520. allocator_binder< \
  521. typename decay<Handler>::type, Allocator>( \
  522. allocator_, BOOST_ASIO_MOVE_CAST(Handler)(handler)), \
  523. BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  524. } \
  525. /**/
  526. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF)
  527. #undef BOOST_ASIO_PRIVATE_INIT_WRAPPER_DEF
  528. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  529. Allocator allocator_;
  530. Initiation initiation_;
  531. };
  532. #if defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  533. template <typename Initiation, typename RawCompletionToken, typename... Args>
  534. static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
  535. (async_initiate<T, Signature>(
  536. declval<init_wrapper<typename decay<Initiation>::type> >(),
  537. declval<RawCompletionToken>().get(),
  538. declval<BOOST_ASIO_MOVE_ARG(Args)>()...)))
  539. initiate(
  540. BOOST_ASIO_MOVE_ARG(Initiation) initiation,
  541. BOOST_ASIO_MOVE_ARG(RawCompletionToken) token,
  542. BOOST_ASIO_MOVE_ARG(Args)... args)
  543. {
  544. return async_initiate<T, Signature>(
  545. init_wrapper<typename decay<Initiation>::type>(
  546. token.get_allocator(),
  547. BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
  548. token.get(), BOOST_ASIO_MOVE_CAST(Args)(args)...);
  549. }
  550. #else // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  551. template <typename Initiation, typename RawCompletionToken>
  552. static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,
  553. (async_initiate<T, Signature>(
  554. declval<init_wrapper<typename decay<Initiation>::type> >(),
  555. declval<RawCompletionToken>().get())))
  556. initiate(
  557. BOOST_ASIO_MOVE_ARG(Initiation) initiation,
  558. BOOST_ASIO_MOVE_ARG(RawCompletionToken) token)
  559. {
  560. return async_initiate<T, Signature>(
  561. init_wrapper<typename decay<Initiation>::type>(
  562. token.get_allocator(),
  563. BOOST_ASIO_MOVE_CAST(Initiation)(initiation)),
  564. token.get());
  565. }
  566. #define BOOST_ASIO_PRIVATE_INITIATE_DEF(n) \
  567. template <typename Initiation, typename RawCompletionToken, \
  568. BOOST_ASIO_VARIADIC_TPARAMS(n)> \
  569. static BOOST_ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \
  570. (async_initiate<T, Signature>( \
  571. declval<init_wrapper<typename decay<Initiation>::type> >(), \
  572. declval<RawCompletionToken>().get(), \
  573. BOOST_ASIO_VARIADIC_MOVE_DECLVAL(n)))) \
  574. initiate( \
  575. BOOST_ASIO_MOVE_ARG(Initiation) initiation, \
  576. BOOST_ASIO_MOVE_ARG(RawCompletionToken) token, \
  577. BOOST_ASIO_VARIADIC_MOVE_PARAMS(n)) \
  578. { \
  579. return async_initiate<T, Signature>( \
  580. init_wrapper<typename decay<Initiation>::type>( \
  581. token.get_allocator(), \
  582. BOOST_ASIO_MOVE_CAST(Initiation)(initiation)), \
  583. token.get(), BOOST_ASIO_VARIADIC_MOVE_ARGS(n)); \
  584. } \
  585. /**/
  586. BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_INITIATE_DEF)
  587. #undef BOOST_ASIO_PRIVATE_INITIATE_DEF
  588. #endif // defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
  589. private:
  590. async_result(const async_result&) BOOST_ASIO_DELETED;
  591. async_result& operator=(const async_result&) BOOST_ASIO_DELETED;
  592. async_result<T, Signature> target_;
  593. };
  594. template <template <typename, typename> class Associator,
  595. typename T, typename Allocator, typename DefaultCandidate>
  596. struct associator<Associator,
  597. allocator_binder<T, Allocator>,
  598. DefaultCandidate>
  599. : Associator<T, DefaultCandidate>
  600. {
  601. static typename Associator<T, DefaultCandidate>::type
  602. get(const allocator_binder<T, Allocator>& b) BOOST_ASIO_NOEXCEPT
  603. {
  604. return Associator<T, DefaultCandidate>::get(b.get());
  605. }
  606. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
  607. typename Associator<T, DefaultCandidate>::type)
  608. get(const allocator_binder<T, Allocator>& b,
  609. const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
  610. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
  611. Associator<T, DefaultCandidate>::get(b.get(), c)))
  612. {
  613. return Associator<T, DefaultCandidate>::get(b.get(), c);
  614. }
  615. };
  616. template <typename T, typename Allocator, typename Allocator1>
  617. struct associated_allocator<
  618. allocator_binder<T, Allocator>,
  619. Allocator1>
  620. {
  621. typedef Allocator type;
  622. static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(
  623. const allocator_binder<T, Allocator>& b,
  624. const Allocator1& = Allocator1()) BOOST_ASIO_NOEXCEPT
  625. BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_allocator()))
  626. {
  627. return b.get_allocator();
  628. }
  629. };
  630. #endif // !defined(GENERATING_DOCUMENTATION)
  631. } // namespace asio
  632. } // namespace boost
  633. #include <boost/asio/detail/pop_options.hpp>
  634. #endif // BOOST_ASIO_BIND_ALLOCATOR_HPP