dispatch_uses_allocator.hpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2015-2015. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/container for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
  11. #define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP
  12. #if defined (_MSC_VER)
  13. # pragma once
  14. #endif
  15. #include <boost/container/detail/config_begin.hpp>
  16. #include <boost/container/detail/workaround.hpp>
  17. #include <boost/container/allocator_traits.hpp>
  18. #include <boost/container/uses_allocator.hpp>
  19. #include <boost/container/detail/addressof.hpp>
  20. #include <boost/container/detail/mpl.hpp>
  21. #include <boost/container/detail/pair.hpp>
  22. #include <boost/container/detail/type_traits.hpp>
  23. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  24. #include <boost/move/detail/fwd_macros.hpp>
  25. #endif
  26. #include <boost/move/utility_core.hpp>
  27. #include <boost/core/no_exceptions_support.hpp>
  28. namespace boost { namespace container {
  29. namespace dtl {
  30. // Check if we can detect is_convertible using advanced SFINAE expressions
  31. #if !defined(BOOST_NO_CXX11_DECLTYPE) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  32. //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
  33. //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
  34. //! Thanks Mathias!
  35. //With variadic templates, we need a single class to implement the trait
  36. template<class T, class ...Args>
  37. struct is_constructible
  38. {
  39. typedef char yes_type;
  40. struct no_type
  41. { char padding[2]; };
  42. template<std::size_t N>
  43. struct dummy;
  44. template<class X>
  45. static decltype(X(boost::move_detail::declval<Args>()...), true_type()) test(int);
  46. template<class X>
  47. static no_type test(...);
  48. static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
  49. };
  50. template <class T, class InnerAlloc, class ...Args>
  51. struct is_constructible_with_allocator_prefix
  52. : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
  53. {};
  54. #else // #if !defined(BOOST_NO_SFINAE_EXPR) && !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  55. //Without advanced SFINAE expressions, we can't use is_constructible
  56. //so backup to constructible_with_allocator_xxx
  57. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  58. template <class T, class InnerAlloc, class ...Args>
  59. struct is_constructible_with_allocator_prefix
  60. : constructible_with_allocator_prefix<T>
  61. {};
  62. template <class T, class InnerAlloc, class ...Args>
  63. struct is_constructible_with_allocator_suffix
  64. : constructible_with_allocator_suffix<T>
  65. {};
  66. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  67. template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
  68. struct is_constructible_with_allocator_prefix
  69. : constructible_with_allocator_prefix<T>
  70. {};
  71. template <class T, class InnerAlloc, BOOST_MOVE_CLASSDFLT9>
  72. struct is_constructible_with_allocator_suffix
  73. : constructible_with_allocator_suffix<T>
  74. {};
  75. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  76. #endif // #if !defined(BOOST_NO_SFINAE_EXPR)
  77. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  78. template < typename ConstructAlloc
  79. , typename ArgAlloc
  80. , typename T
  81. , class ...Args
  82. >
  83. inline typename dtl::enable_if_and
  84. < void
  85. , dtl::is_not_pair<T>
  86. , dtl::not_< uses_allocator<T, ArgAlloc> >
  87. >::type dispatch_uses_allocator
  88. ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
  89. {
  90. (void)arg_alloc;
  91. allocator_traits<ConstructAlloc>::construct(construct_alloc, p, ::boost::forward<Args>(args)...);
  92. }
  93. // allocator_arg_t
  94. template < typename ConstructAlloc
  95. , typename ArgAlloc
  96. , typename T
  97. , class ...Args
  98. >
  99. inline typename dtl::enable_if_and
  100. < void
  101. , dtl::is_not_pair<T>
  102. , uses_allocator<T, ArgAlloc>
  103. , is_constructible_with_allocator_prefix<T, ArgAlloc, Args...>
  104. >::type dispatch_uses_allocator
  105. ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args) ...args)
  106. {
  107. allocator_traits<ConstructAlloc>::construct
  108. ( construct_alloc, p, allocator_arg
  109. , ::boost::forward<ArgAlloc>(arg_alloc), ::boost::forward<Args>(args)...);
  110. }
  111. // allocator suffix
  112. template < typename ConstructAlloc
  113. , typename ArgAlloc
  114. , typename T
  115. , class ...Args
  116. >
  117. inline typename dtl::enable_if_and
  118. < void
  119. , dtl::is_not_pair<T>
  120. , uses_allocator<T, ArgAlloc>
  121. , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc, Args...> >
  122. >::type dispatch_uses_allocator
  123. ( ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p, BOOST_FWD_REF(Args)...args)
  124. {
  125. allocator_traits<ConstructAlloc>::construct
  126. (construct_alloc, p, ::boost::forward<Args>(args)..., ::boost::forward<ArgAlloc>(arg_alloc));
  127. }
  128. #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  129. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
  130. template <typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  131. inline typename dtl::enable_if_and\
  132. < void\
  133. , dtl::is_not_pair<T>\
  134. , dtl::not_<uses_allocator<T, ArgAlloc> >\
  135. >::type\
  136. dispatch_uses_allocator\
  137. (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  138. {\
  139. (void)arg_alloc;\
  140. allocator_traits<ConstructAlloc>::construct(construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  141. }\
  142. //
  143. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
  144. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
  145. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
  146. template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  147. inline typename dtl::enable_if_and\
  148. < void\
  149. , dtl::is_not_pair<T>\
  150. , uses_allocator<T, ArgAlloc>\
  151. , is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N>\
  152. >::type\
  153. dispatch_uses_allocator\
  154. (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  155. {\
  156. allocator_traits<ConstructAlloc>::construct\
  157. (construct_alloc, p, allocator_arg, ::boost::forward<ArgAlloc>(arg_alloc) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  158. }\
  159. //
  160. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
  161. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
  162. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE(N) \
  163. template < typename ConstructAlloc, typename ArgAlloc, typename T BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  164. inline typename dtl::enable_if_and\
  165. < void\
  166. , dtl::is_not_pair<T>\
  167. , uses_allocator<T, ArgAlloc>\
  168. , dtl::not_<is_constructible_with_allocator_prefix<T, ArgAlloc BOOST_MOVE_I##N BOOST_MOVE_TARG##N> >\
  169. >::type\
  170. dispatch_uses_allocator\
  171. (ConstructAlloc& construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, T* p BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  172. {\
  173. allocator_traits<ConstructAlloc>::construct\
  174. (construct_alloc, p BOOST_MOVE_I##N BOOST_MOVE_FWD##N, ::boost::forward<ArgAlloc>(arg_alloc));\
  175. }\
  176. //
  177. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE)
  178. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_DISPATCH_USES_ALLOCATOR_CODE
  179. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  180. template < typename ConstructAlloc
  181. , typename ArgAlloc
  182. , typename Pair
  183. > inline
  184. BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void >::type)
  185. dispatch_uses_allocator
  186. ( ConstructAlloc & construct_alloc
  187. , BOOST_FWD_REF(ArgAlloc) arg_alloc
  188. , Pair* p)
  189. {
  190. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first));
  191. BOOST_TRY{
  192. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second));
  193. }
  194. BOOST_CATCH(...) {
  195. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
  196. BOOST_RETHROW
  197. }
  198. BOOST_CATCH_END
  199. }
  200. template < typename ConstructAlloc
  201. , typename ArgAlloc
  202. , class Pair, class U, class V>
  203. BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if<dtl::is_pair<Pair> BOOST_MOVE_I void>::type)
  204. dispatch_uses_allocator
  205. ( ConstructAlloc & construct_alloc
  206. , BOOST_FWD_REF(ArgAlloc) arg_alloc
  207. , Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  208. {
  209. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<U>(x));
  210. BOOST_TRY{
  211. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<V>(y));
  212. }
  213. BOOST_CATCH(...){
  214. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
  215. BOOST_RETHROW
  216. }
  217. BOOST_CATCH_END
  218. }
  219. template < typename ConstructAlloc
  220. , typename ArgAlloc
  221. , class Pair, class Pair2>
  222. BOOST_CONTAINER_DOC1ST(void, typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void >::type)
  223. dispatch_uses_allocator
  224. (ConstructAlloc & construct_alloc
  225. , BOOST_FWD_REF(ArgAlloc) arg_alloc
  226. , Pair* p, Pair2& x)
  227. { (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, x.first, x.second); }
  228. template < typename ConstructAlloc
  229. , typename ArgAlloc
  230. , class Pair, class Pair2>
  231. typename dtl::enable_if_and
  232. < void
  233. , dtl::is_pair<Pair>
  234. , dtl::not_<boost::move_detail::is_reference<Pair2> > >::type //This is needed for MSVC10 and ambiguous overloads
  235. dispatch_uses_allocator
  236. (ConstructAlloc & construct_alloc
  237. , BOOST_FWD_REF(ArgAlloc) arg_alloc
  238. , Pair* p, BOOST_RV_REF_BEG Pair2 BOOST_RV_REF_END x)
  239. { (dispatch_uses_allocator)(construct_alloc, arg_alloc, p, ::boost::move(x.first), ::boost::move(x.second)); }
  240. //piecewise construction from boost::tuple
  241. #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE(N,M)\
  242. template< typename ConstructAlloc, typename ArgAlloc, class Pair \
  243. , template<class, class, class, class, class, class, class, class, class, class> class BoostTuple \
  244. BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
  245. typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
  246. dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
  247. , BoostTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::boost::tuples::null_type)> p\
  248. , BoostTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::boost::tuples::null_type)> q)\
  249. {\
  250. (void)p; (void)q;\
  251. (dispatch_uses_allocator)\
  252. (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_TMPL_GET##N);\
  253. BOOST_TRY{\
  254. (dispatch_uses_allocator)\
  255. (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_TMPL_GETQ##M);\
  256. }\
  257. BOOST_CATCH(...) {\
  258. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
  259. BOOST_RETHROW\
  260. }\
  261. BOOST_CATCH_END\
  262. }\
  263. //
  264. BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE)
  265. #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_BOOST_TUPLE_CODE
  266. //piecewise construction from Std Tuple
  267. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  268. template< typename ConstructAlloc, typename ArgAlloc, class Pair
  269. , template<class ...> class Tuple, class... Args1, class... Args2, size_t... Indexes1, size_t... Indexes2>
  270. void dispatch_uses_allocator_index( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair
  271. , Tuple<Args1...>& t1, Tuple<Args2...>& t2, index_tuple<Indexes1...>, index_tuple<Indexes2...>)
  272. {
  273. (void)t1; (void)t2;
  274. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(pair->first), ::boost::forward<Args1>(get<Indexes1>(t1))...);
  275. BOOST_TRY{
  276. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(pair->second), ::boost::forward<Args2>(get<Indexes2>(t2))...);
  277. }
  278. BOOST_CATCH(...){
  279. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));
  280. BOOST_RETHROW
  281. }
  282. BOOST_CATCH_END
  283. }
  284. template< typename ConstructAlloc, typename ArgAlloc, class Pair
  285. , template<class ...> class Tuple, class... Args1, class... Args2>
  286. typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
  287. dispatch_uses_allocator( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t
  288. , Tuple<Args1...> t1, Tuple<Args2...> t2)
  289. {
  290. (dispatch_uses_allocator_index)( construct_alloc, arg_alloc, pair, t1, t2
  291. , typename build_number_seq<sizeof...(Args1)>::type()
  292. , typename build_number_seq<sizeof...(Args2)>::type());
  293. }
  294. #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 520)
  295. //MSVC 2010 tuple implementation
  296. #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE(N,M)\
  297. template< typename ConstructAlloc, typename ArgAlloc, class Pair\
  298. , template<class, class, class, class, class, class, class, class, class, class> class StdTuple\
  299. BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
  300. typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
  301. dispatch_uses_allocator(ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
  302. , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,N),::std::tr1::_Nil)> p\
  303. , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(10,M),::std::tr1::_Nil)> q)\
  304. {\
  305. (void)p; (void)q;\
  306. (dispatch_uses_allocator)\
  307. (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
  308. BOOST_TRY{\
  309. (dispatch_uses_allocator)\
  310. (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
  311. }\
  312. BOOST_CATCH(...) {\
  313. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
  314. BOOST_RETHROW\
  315. }\
  316. BOOST_CATCH_END\
  317. }\
  318. //
  319. BOOST_MOVE_ITER2D_0TOMAX(9, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE)
  320. #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
  321. #elif defined(BOOST_MSVC) && (_CPPLIB_VER == 540)
  322. #if _VARIADIC_MAX >= 9
  323. #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT 9
  324. #else
  325. #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT BOOST_MOVE_ADD(_VARIADIC_MAX, 1)
  326. #endif
  327. //MSVC 2012 tuple implementation
  328. #define BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE(N,M)\
  329. template< typename ConstructAlloc, typename ArgAlloc, class Pair\
  330. , template<BOOST_MOVE_REPEAT(_VARIADIC_MAX, class), class, class, class> class StdTuple \
  331. BOOST_MOVE_I_IF(BOOST_MOVE_OR(N,M)) BOOST_MOVE_CLASS##N BOOST_MOVE_I_IF(BOOST_MOVE_AND(N,M)) BOOST_MOVE_CLASSQ##M > \
  332. typename dtl::enable_if< dtl::is_pair<Pair> BOOST_MOVE_I void>::type\
  333. dispatch_uses_allocator\
  334. ( ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* pair, piecewise_construct_t\
  335. , StdTuple<BOOST_MOVE_TARG##N BOOST_MOVE_I##N BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),N),::std::_Nil) > p\
  336. , StdTuple<BOOST_MOVE_TARGQ##M BOOST_MOVE_I##M BOOST_MOVE_REPEAT(BOOST_MOVE_SUB(BOOST_MOVE_ADD(_VARIADIC_MAX, 3),M),::std::_Nil) > q)\
  337. {\
  338. (void)p; (void)q;\
  339. (dispatch_uses_allocator)\
  340. (construct_alloc, arg_alloc, dtl::addressof(pair->first) BOOST_MOVE_I_IF(N) BOOST_MOVE_GET_IDX##N);\
  341. BOOST_TRY{\
  342. (dispatch_uses_allocator)\
  343. (construct_alloc, arg_alloc, dtl::addressof(pair->second) BOOST_MOVE_I_IF(M) BOOST_MOVE_GET_IDXQ##M);\
  344. }\
  345. BOOST_CATCH(...) {\
  346. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(pair->first));\
  347. BOOST_RETHROW\
  348. }\
  349. BOOST_CATCH_END\
  350. }\
  351. //
  352. BOOST_MOVE_ITER2D_0TOMAX(BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT, BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_CODE)
  353. #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2010_TUPLE_CODE
  354. #undef BOOST_DISPATCH_USES_ALLOCATOR_PIECEWISE_CONSTRUCT_MSVC2012_TUPLE_MAX_IT
  355. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  356. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  357. template < typename ConstructAlloc
  358. , typename ArgAlloc
  359. , class Pair, class KeyType, class ... Args>
  360. typename dtl::enable_if< dtl::is_pair<Pair>, void >::type
  361. dispatch_uses_allocator
  362. (ConstructAlloc & construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, BOOST_FWD_REF(KeyType) k, BOOST_FWD_REF(Args) ...args)
  363. {
  364. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));
  365. BOOST_TRY{
  366. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second), ::boost::forward<Args>(args)...);
  367. }
  368. BOOST_CATCH(...) {
  369. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));
  370. BOOST_RETHROW
  371. }
  372. BOOST_CATCH_END
  373. }
  374. #else
  375. #define BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE(N) \
  376. template <typename ConstructAlloc, typename ArgAlloc, class Pair, class KeyType BOOST_MOVE_I##N BOOST_MOVE_CLASS##N >\
  377. inline typename dtl::enable_if\
  378. < dtl::is_pair<Pair> BOOST_MOVE_I void >::type\
  379. dispatch_uses_allocator\
  380. (ConstructAlloc &construct_alloc, BOOST_FWD_REF(ArgAlloc) arg_alloc, Pair* p, try_emplace_t, \
  381. BOOST_FWD_REF(KeyType) k BOOST_MOVE_I##N BOOST_MOVE_UREF##N)\
  382. {\
  383. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->first), ::boost::forward<KeyType>(k));\
  384. BOOST_TRY{\
  385. (dispatch_uses_allocator)(construct_alloc, arg_alloc, dtl::addressof(p->second) BOOST_MOVE_I##N BOOST_MOVE_FWD##N);\
  386. }\
  387. BOOST_CATCH(...) {\
  388. allocator_traits<ConstructAlloc>::destroy(construct_alloc, dtl::addressof(p->first));\
  389. BOOST_RETHROW\
  390. }\
  391. BOOST_CATCH_END\
  392. }\
  393. //
  394. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE)
  395. #undef BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_PAIR_TRY_EMPLACE_CODE
  396. #endif //!defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  397. } //namespace dtl
  398. }} // namespace boost { namespace container {
  399. #include <boost/container/detail/config_end.hpp>
  400. #endif // BOOST_CONTAINER_DISPATCH_USES_ALLOCATOR_HPP