bind_allocator.hpp 20 KB

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