scoped_allocator.hpp 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Pablo Halpern 2009. 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. //////////////////////////////////////////////////////////////////////////////
  8. //
  9. // (C) Copyright Ion Gaztanaga 2011-2012. Distributed under the Boost
  10. // Software License, Version 1.0. (See accompanying file
  11. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // See http://www.boost.org/libs/container for documentation.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
  17. #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
  18. #if defined (_MSC_VER)
  19. # pragma once
  20. #endif
  21. #include <boost/container/detail/config_begin.hpp>
  22. #include <boost/container/detail/workaround.hpp>
  23. #include <boost/container/scoped_allocator_fwd.hpp>
  24. #include <boost/type_traits/integral_constant.hpp>
  25. #include <boost/container/allocator_traits.hpp>
  26. #include <boost/container/detail/type_traits.hpp>
  27. #include <boost/container/detail/utilities.hpp>
  28. #include <utility>
  29. #include <boost/container/detail/pair.hpp>
  30. #include <boost/move/utility.hpp>
  31. #include <boost/detail/no_exceptions_support.hpp>
  32. namespace boost { namespace container {
  33. //! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed
  34. //! with an allocator as its last constructor argument. Ideally, all constructors of T (including the
  35. //! copy and move constructors) should have a variant that accepts a final argument of
  36. //! allocator_type.
  37. //!
  38. //! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type,
  39. //! allocator_type and at least one constructor for which allocator_type is the last
  40. //! parameter. If not all constructors of T can be called with a final allocator_type argument,
  41. //! and if T is used in a context where a container must call such a constructor, then the program is
  42. //! ill-formed.
  43. //!
  44. //! [Example:
  45. //! template <class T, class Allocator = allocator<T> >
  46. //! class Z {
  47. //! public:
  48. //! typedef Allocator allocator_type;
  49. //!
  50. //! // Default constructor with optional allocator suffix
  51. //! Z(const allocator_type& a = allocator_type());
  52. //!
  53. //! // Copy constructor and allocator-extended copy constructor
  54. //! Z(const Z& zz);
  55. //! Z(const Z& zz, const allocator_type& a);
  56. //! };
  57. //!
  58. //! // Specialize trait for class template Z
  59. //! template <class T, class Allocator = allocator<T> >
  60. //! struct constructible_with_allocator_suffix<Z<T,Allocator> >
  61. //! : ::boost::true_type { };
  62. //! -- end example]
  63. //!
  64. //! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
  65. //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
  66. //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
  67. //! Applications aiming portability with several compilers should always define this trait.
  68. //!
  69. //! In conforming C++11 compilers or compilers supporting SFINAE expressions
  70. //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
  71. //! to detect if a type should be constructed with suffix or prefix allocator arguments.
  72. template <class T>
  73. struct constructible_with_allocator_suffix
  74. : ::boost::false_type
  75. {};
  76. //! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed
  77. //! with allocator_arg and T::allocator_type as its first two constructor arguments.
  78. //! Ideally, all constructors of T (including the copy and move constructors) should have a variant
  79. //! that accepts these two initial arguments.
  80. //!
  81. //! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type,
  82. //! allocator_type and at least one constructor for which allocator_arg_t is the first
  83. //! parameter and allocator_type is the second parameter. If not all constructors of T can be
  84. //! called with these initial arguments, and if T is used in a context where a container must call such
  85. //! a constructor, then the program is ill-formed.
  86. //!
  87. //! [Example:
  88. //! template <class T, class Allocator = allocator<T> >
  89. //! class Y {
  90. //! public:
  91. //! typedef Allocator allocator_type;
  92. //!
  93. //! // Default constructor with and allocator-extended default constructor
  94. //! Y();
  95. //! Y(allocator_arg_t, const allocator_type& a);
  96. //!
  97. //! // Copy constructor and allocator-extended copy constructor
  98. //! Y(const Y& yy);
  99. //! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
  100. //!
  101. //! // Variadic constructor and allocator-extended variadic constructor
  102. //! template<class ...Args> Y(Args&& args...);
  103. //! template<class ...Args>
  104. //! Y(allocator_arg_t, const allocator_type& a, Args&&... args);
  105. //! };
  106. //!
  107. //! // Specialize trait for class template Y
  108. //! template <class T, class Allocator = allocator<T> >
  109. //! struct constructible_with_allocator_prefix<Y<T,Allocator> >
  110. //! : ::boost::true_type { };
  111. //!
  112. //! -- end example]
  113. //!
  114. //! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
  115. //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
  116. //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
  117. //! Applications aiming portability with several compilers should always define this trait.
  118. //!
  119. //! In conforming C++11 compilers or compilers supporting SFINAE expressions
  120. //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
  121. //! to detect if a type should be constructed with suffix or prefix allocator arguments.
  122. template <class T>
  123. struct constructible_with_allocator_prefix
  124. : ::boost::false_type
  125. {};
  126. ///@cond
  127. namespace container_detail {
  128. template<typename T, typename Alloc>
  129. struct uses_allocator_imp
  130. {
  131. // Use SFINAE (Substitution Failure Is Not An Error) to detect the
  132. // presence of an 'allocator_type' nested type convertilble from Alloc.
  133. private:
  134. // Match this function if TypeT::allocator_type exists and is
  135. // implicitly convertible from Alloc
  136. template <typename U>
  137. static char test(int, typename U::allocator_type);
  138. // Match this function if TypeT::allocator_type does not exist or is
  139. // not convertible from Alloc.
  140. template <typename U>
  141. static int test(LowPriorityConversion<int>, LowPriorityConversion<Alloc>);
  142. static Alloc alloc; // Declared but not defined
  143. public:
  144. enum { value = sizeof(test<T>(0, alloc)) == sizeof(char) };
  145. };
  146. } //namespace container_detail {
  147. ///@endcond
  148. //! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from
  149. //! Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
  150. //! specialize this type to derive from true_type for a T of user-defined type if T does not
  151. //! have a nested allocator_type but is nonetheless constructible using the specified Alloc.
  152. //!
  153. //! <b>Result</b>: derived from true_type if Convertible<Alloc,T::allocator_type> and
  154. //! derived from false_type otherwise.
  155. template <typename T, typename Alloc>
  156. struct uses_allocator
  157. : boost::integral_constant<bool, container_detail::uses_allocator_imp<T, Alloc>::value>
  158. {};
  159. ///@cond
  160. namespace container_detail {
  161. template <typename Alloc>
  162. struct is_scoped_allocator_imp
  163. {
  164. template <typename T>
  165. static char test(int, typename T::outer_allocator_type*);
  166. template <typename T>
  167. static int test(LowPriorityConversion<int>, void*);
  168. static const bool value = (sizeof(char) == sizeof(test<Alloc>(0, 0)));
  169. };
  170. template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
  171. struct outermost_allocator_type_impl
  172. {
  173. typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
  174. typedef typename outermost_allocator_type_impl<outer_type>::type type;
  175. };
  176. template<class MaybeScopedAlloc>
  177. struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
  178. {
  179. typedef MaybeScopedAlloc type;
  180. };
  181. template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
  182. struct outermost_allocator_imp
  183. {
  184. typedef MaybeScopedAlloc type;
  185. static type &get(MaybeScopedAlloc &a)
  186. { return a; }
  187. static const type &get(const MaybeScopedAlloc &a)
  188. { return a; }
  189. };
  190. template<class MaybeScopedAlloc>
  191. struct outermost_allocator_imp<MaybeScopedAlloc, true>
  192. {
  193. typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
  194. typedef typename outermost_allocator_type_impl<outer_type>::type type;
  195. static type &get(MaybeScopedAlloc &a)
  196. { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
  197. static const type &get(const MaybeScopedAlloc &a)
  198. { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
  199. };
  200. } //namespace container_detail {
  201. template <typename Alloc>
  202. struct is_scoped_allocator
  203. : boost::integral_constant<bool, container_detail::is_scoped_allocator_imp<Alloc>::value>
  204. {};
  205. template <typename Alloc>
  206. struct outermost_allocator
  207. : container_detail::outermost_allocator_imp<Alloc>
  208. {};
  209. template <typename Alloc>
  210. typename container_detail::outermost_allocator_imp<Alloc>::type &
  211. get_outermost_allocator(Alloc &a)
  212. { return container_detail::outermost_allocator_imp<Alloc>::get(a); }
  213. template <typename Alloc>
  214. const typename container_detail::outermost_allocator_imp<Alloc>::type &
  215. get_outermost_allocator(const Alloc &a)
  216. { return container_detail::outermost_allocator_imp<Alloc>::get(a); }
  217. namespace container_detail {
  218. // Check if we can detect is_convertible using advanced SFINAE expressions
  219. #if !defined(BOOST_NO_SFINAE_EXPR)
  220. //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
  221. //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
  222. //! Thanks Mathias!
  223. //With variadic templates, we need a single class to implement the trait
  224. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  225. template<class T, class ...Args>
  226. struct is_constructible_impl
  227. {
  228. typedef char yes_type;
  229. struct no_type
  230. { char padding[2]; };
  231. template<std::size_t N>
  232. struct dummy;
  233. template<class X>
  234. static yes_type test(dummy<sizeof(X(boost::move_detail::declval<Args>()...))>*);
  235. template<class X>
  236. static no_type test(...);
  237. static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
  238. };
  239. template<class T, class ...Args>
  240. struct is_constructible
  241. : boost::integral_constant<bool, is_constructible_impl<T, Args...>::value>
  242. {};
  243. template <class T, class InnerAlloc, class ...Args>
  244. struct is_constructible_with_allocator_prefix
  245. : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
  246. {};
  247. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  248. //Without variadic templates, we need to use de preprocessor to generate
  249. //some specializations.
  250. #define BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS \
  251. BOOST_PP_ADD(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, 3)
  252. //!
  253. //Generate N+1 template parameters so that we can specialize N
  254. template<class T
  255. BOOST_PP_ENUM_TRAILING( BOOST_PP_ADD(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
  256. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  257. , void)
  258. >
  259. struct is_constructible_impl;
  260. //Generate N specializations, from 0 to
  261. //BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS parameters
  262. #define BOOST_PP_LOCAL_MACRO(n) \
  263. template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)> \
  264. struct is_constructible_impl \
  265. <T BOOST_PP_ENUM_TRAILING_PARAMS(n, P) \
  266. BOOST_PP_ENUM_TRAILING \
  267. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, n) \
  268. , BOOST_CONTAINER_PP_IDENTITY, void) \
  269. , void> \
  270. { \
  271. typedef char yes_type; \
  272. struct no_type \
  273. { char padding[2]; }; \
  274. \
  275. template<std::size_t N> \
  276. struct dummy; \
  277. \
  278. template<class X> \
  279. static yes_type test(dummy<sizeof(X(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_DECLVAL, ~)))>*); \
  280. \
  281. template<class X> \
  282. static no_type test(...); \
  283. \
  284. static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); \
  285. }; \
  286. //!
  287. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS)
  288. #include BOOST_PP_LOCAL_ITERATE()
  289. //Finally just inherit from the implementation to define he trait
  290. template< class T
  291. BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS
  292. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  293. , void)
  294. >
  295. struct is_constructible
  296. : boost::integral_constant
  297. < bool
  298. , is_constructible_impl
  299. < T
  300. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, P)
  301. , void>::value
  302. >
  303. {};
  304. //Finally just inherit from the implementation to define he trait
  305. template <class T
  306. ,class InnerAlloc
  307. BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2)
  308. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  309. , void)
  310. >
  311. struct is_constructible_with_allocator_prefix
  312. : is_constructible
  313. < T, allocator_arg_t, InnerAlloc
  314. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2), P)
  315. >
  316. {};
  317. /*
  318. template <class T
  319. ,class InnerAlloc
  320. BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
  321. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  322. , void)
  323. >
  324. struct is_constructible_with_allocator_suffix
  325. : is_constructible
  326. < T
  327. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1), P)
  328. , InnerAlloc
  329. >
  330. {};*/
  331. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  332. #else // #if !defined(BOOST_NO_SFINAE_EXPR)
  333. //Without advanced SFINAE expressions, we can't use is_constructible
  334. //so backup to constructible_with_allocator_xxx
  335. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  336. template < class T, class InnerAlloc, class ...Args>
  337. struct is_constructible_with_allocator_prefix
  338. : constructible_with_allocator_prefix<T>
  339. {};
  340. /*
  341. template < class T, class InnerAlloc, class ...Args>
  342. struct is_constructible_with_allocator_suffix
  343. : constructible_with_allocator_suffix<T>
  344. {};*/
  345. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  346. template < class T
  347. , class InnerAlloc
  348. BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
  349. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  350. , void)
  351. >
  352. struct is_constructible_with_allocator_prefix
  353. : constructible_with_allocator_prefix<T>
  354. {};
  355. /*
  356. template < class T
  357. , class InnerAlloc
  358. BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
  359. , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
  360. , void)
  361. >
  362. struct is_constructible_with_allocator_suffix
  363. : constructible_with_allocator_suffix<T>
  364. {};*/
  365. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  366. #endif // #if !defined(BOOST_NO_SFINAE_EXPR)
  367. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  368. template < typename OutermostAlloc
  369. , typename InnerAlloc
  370. , typename T
  371. , class ...Args
  372. >
  373. inline void dispatch_allocator_prefix_suffix
  374. ( boost::true_type use_alloc_prefix, OutermostAlloc& outermost_alloc
  375. , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args) ...args)
  376. {
  377. (void)use_alloc_prefix;
  378. allocator_traits<OutermostAlloc>::construct
  379. ( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward<Args>(args)...);
  380. }
  381. template < typename OutermostAlloc
  382. , typename InnerAlloc
  383. , typename T
  384. , class ...Args
  385. >
  386. inline void dispatch_allocator_prefix_suffix
  387. ( boost::false_type use_alloc_prefix, OutermostAlloc& outermost_alloc
  388. , InnerAlloc &inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
  389. {
  390. (void)use_alloc_prefix;
  391. allocator_traits<OutermostAlloc>::construct
  392. (outermost_alloc, p, ::boost::forward<Args>(args)..., inner_alloc);
  393. }
  394. template < typename OutermostAlloc
  395. , typename InnerAlloc
  396. , typename T
  397. , class ...Args
  398. >
  399. inline void dispatch_uses_allocator
  400. ( boost::true_type uses_allocator, OutermostAlloc& outermost_alloc
  401. , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
  402. {
  403. (void)uses_allocator;
  404. //BOOST_STATIC_ASSERT((is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value ||
  405. // is_constructible_with_allocator_suffix<T, InnerAlloc, Args...>::value ));
  406. dispatch_allocator_prefix_suffix
  407. ( is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>()
  408. , outermost_alloc, inner_alloc, p, ::boost::forward<Args>(args)...);
  409. }
  410. template < typename OutermostAlloc
  411. , typename InnerAlloc
  412. , typename T
  413. , class ...Args
  414. >
  415. inline void dispatch_uses_allocator
  416. ( boost::false_type uses_allocator, OutermostAlloc & outermost_alloc
  417. , InnerAlloc & inner_alloc
  418. ,T* p, BOOST_FWD_REF(Args)...args)
  419. {
  420. (void)uses_allocator; (void)inner_alloc;
  421. allocator_traits<OutermostAlloc>::construct
  422. (outermost_alloc, p, ::boost::forward<Args>(args)...);
  423. }
  424. #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  425. #define BOOST_PP_LOCAL_MACRO(n) \
  426. template < typename OutermostAlloc \
  427. , typename InnerAlloc \
  428. , typename T \
  429. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  430. > \
  431. inline void dispatch_allocator_prefix_suffix( \
  432. boost::true_type use_alloc_prefix, \
  433. OutermostAlloc& outermost_alloc, \
  434. InnerAlloc& inner_alloc, \
  435. T* p \
  436. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  437. { \
  438. (void)use_alloc_prefix, \
  439. allocator_traits<OutermostAlloc>::construct \
  440. (outermost_alloc, p, allocator_arg, inner_alloc \
  441. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
  442. } \
  443. \
  444. template < typename OutermostAlloc \
  445. , typename InnerAlloc \
  446. , typename T \
  447. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  448. > \
  449. inline void dispatch_allocator_prefix_suffix( \
  450. boost::false_type use_alloc_prefix, \
  451. OutermostAlloc& outermost_alloc, \
  452. InnerAlloc& inner_alloc, \
  453. T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  454. { \
  455. (void)use_alloc_prefix; \
  456. allocator_traits<OutermostAlloc>::construct \
  457. (outermost_alloc, p \
  458. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
  459. , inner_alloc); \
  460. } \
  461. \
  462. template < typename OutermostAlloc \
  463. , typename InnerAlloc \
  464. , typename T \
  465. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  466. > \
  467. inline void dispatch_uses_allocator(boost::true_type uses_allocator, \
  468. OutermostAlloc& outermost_alloc, \
  469. InnerAlloc& inner_alloc, \
  470. T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  471. { \
  472. (void)uses_allocator; \
  473. dispatch_allocator_prefix_suffix \
  474. (is_constructible_with_allocator_prefix \
  475. < T, InnerAlloc BOOST_PP_ENUM_TRAILING_PARAMS(n, P)>() \
  476. , outermost_alloc, inner_alloc, p \
  477. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
  478. } \
  479. \
  480. template < typename OutermostAlloc \
  481. , typename InnerAlloc \
  482. , typename T \
  483. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  484. > \
  485. inline void dispatch_uses_allocator(boost::false_type uses_allocator \
  486. ,OutermostAlloc & outermost_alloc \
  487. ,InnerAlloc & inner_alloc \
  488. ,T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  489. { \
  490. (void)uses_allocator; (void)inner_alloc; \
  491. allocator_traits<OutermostAlloc>::construct \
  492. (outermost_alloc, p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
  493. } \
  494. //!
  495. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  496. #include BOOST_PP_LOCAL_ITERATE()
  497. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  498. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  499. template <typename OuterAlloc, class ...InnerAllocs>
  500. class scoped_allocator_adaptor_base
  501. : public OuterAlloc
  502. {
  503. typedef allocator_traits<OuterAlloc> outer_traits_type;
  504. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
  505. public:
  506. template <class OuterA2>
  507. struct rebind_base
  508. {
  509. typedef scoped_allocator_adaptor_base<OuterA2, InnerAllocs...> other;
  510. };
  511. typedef OuterAlloc outer_allocator_type;
  512. typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
  513. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  514. typedef scoped_allocator_adaptor
  515. <OuterAlloc, InnerAllocs...> scoped_allocator_type;
  516. typedef boost::integral_constant<
  517. bool,
  518. outer_traits_type::propagate_on_container_copy_assignment::value ||
  519. inner_allocator_type::propagate_on_container_copy_assignment::value
  520. > propagate_on_container_copy_assignment;
  521. typedef boost::integral_constant<
  522. bool,
  523. outer_traits_type::propagate_on_container_move_assignment::value ||
  524. inner_allocator_type::propagate_on_container_move_assignment::value
  525. > propagate_on_container_move_assignment;
  526. typedef boost::integral_constant<
  527. bool,
  528. outer_traits_type::propagate_on_container_swap::value ||
  529. inner_allocator_type::propagate_on_container_swap::value
  530. > propagate_on_container_swap;
  531. scoped_allocator_adaptor_base()
  532. {}
  533. template <class OuterA2>
  534. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
  535. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  536. , m_inner(args...)
  537. {}
  538. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  539. : outer_allocator_type(other.outer_allocator())
  540. , m_inner(other.inner_allocator())
  541. {}
  542. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  543. : outer_allocator_type(::boost::move(other.outer_allocator()))
  544. , m_inner(::boost::move(other.inner_allocator()))
  545. {}
  546. template <class OuterA2>
  547. scoped_allocator_adaptor_base
  548. (const scoped_allocator_adaptor_base<OuterA2, InnerAllocs...>& other)
  549. : outer_allocator_type(other.outer_allocator())
  550. , m_inner(other.inner_allocator())
  551. {}
  552. template <class OuterA2>
  553. scoped_allocator_adaptor_base
  554. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base
  555. <OuterA2, InnerAllocs...> BOOST_RV_REF_END other)
  556. : outer_allocator_type(other.outer_allocator())
  557. , m_inner(other.inner_allocator())
  558. {}
  559. public:
  560. struct internal_type_t{};
  561. template <class OuterA2>
  562. scoped_allocator_adaptor_base
  563. ( internal_type_t
  564. , BOOST_FWD_REF(OuterA2) outerAlloc
  565. , const inner_allocator_type &inner)
  566. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  567. , m_inner(inner)
  568. {}
  569. public:
  570. scoped_allocator_adaptor_base &operator=
  571. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  572. {
  573. outer_allocator_type::operator=(other.outer_allocator());
  574. m_inner = other.inner_allocator();
  575. return *this;
  576. }
  577. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  578. {
  579. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  580. m_inner = ::boost::move(other.inner_allocator());
  581. return *this;
  582. }
  583. void swap(scoped_allocator_adaptor_base &r)
  584. {
  585. boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
  586. boost::container::swap_dispatch(this->m_inner, r.inner_allocator());
  587. }
  588. friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
  589. { l.swap(r); }
  590. inner_allocator_type& inner_allocator()
  591. { return m_inner; }
  592. inner_allocator_type const& inner_allocator() const
  593. { return m_inner; }
  594. outer_allocator_type & outer_allocator()
  595. { return static_cast<outer_allocator_type&>(*this); }
  596. const outer_allocator_type &outer_allocator() const
  597. { return static_cast<const outer_allocator_type&>(*this); }
  598. scoped_allocator_type select_on_container_copy_construction() const
  599. {
  600. return scoped_allocator_type
  601. (internal_type_t()
  602. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
  603. ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
  604. );
  605. }
  606. private:
  607. inner_allocator_type m_inner;
  608. };
  609. #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  610. //Let's add a dummy first template parameter to allow creating
  611. //specializations up to maximum InnerAlloc count
  612. template <
  613. typename OuterAlloc
  614. , bool Dummy
  615. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  616. >
  617. class scoped_allocator_adaptor_base;
  618. //Specializations for the adaptor with InnerAlloc allocators
  619. #define BOOST_PP_LOCAL_MACRO(n) \
  620. template <typename OuterAlloc \
  621. BOOST_PP_ENUM_TRAILING_PARAMS(n, class Q) \
  622. > \
  623. class scoped_allocator_adaptor_base<OuterAlloc, true \
  624. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  625. BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  626. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  627. > \
  628. : public OuterAlloc \
  629. { \
  630. typedef allocator_traits<OuterAlloc> outer_traits_type; \
  631. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) \
  632. \
  633. public: \
  634. template <class OuterA2> \
  635. struct rebind_base \
  636. { \
  637. typedef scoped_allocator_adaptor_base<OuterA2, true BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  638. BOOST_PP_ENUM_TRAILING \
  639. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  640. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  641. > other; \
  642. }; \
  643. \
  644. typedef OuterAlloc outer_allocator_type; \
  645. typedef scoped_allocator_adaptor<BOOST_PP_ENUM_PARAMS(n, Q) \
  646. BOOST_PP_ENUM_TRAILING \
  647. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  648. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  649. > inner_allocator_type; \
  650. typedef scoped_allocator_adaptor<OuterAlloc, BOOST_PP_ENUM_PARAMS(n, Q) \
  651. BOOST_PP_ENUM_TRAILING \
  652. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  653. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  654. > scoped_allocator_type; \
  655. typedef allocator_traits<inner_allocator_type> inner_traits_type; \
  656. typedef boost::integral_constant< \
  657. bool, \
  658. outer_traits_type::propagate_on_container_copy_assignment::value || \
  659. inner_allocator_type::propagate_on_container_copy_assignment::value \
  660. > propagate_on_container_copy_assignment; \
  661. typedef boost::integral_constant< \
  662. bool, \
  663. outer_traits_type::propagate_on_container_move_assignment::value || \
  664. inner_allocator_type::propagate_on_container_move_assignment::value \
  665. > propagate_on_container_move_assignment; \
  666. typedef boost::integral_constant< \
  667. bool, \
  668. outer_traits_type::propagate_on_container_swap::value || \
  669. inner_allocator_type::propagate_on_container_swap::value \
  670. > propagate_on_container_swap; \
  671. \
  672. scoped_allocator_adaptor_base() \
  673. {} \
  674. \
  675. template <class OuterA2> \
  676. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc \
  677. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
  678. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
  679. , m_inner(BOOST_PP_ENUM_PARAMS(n, q)) \
  680. {} \
  681. \
  682. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) \
  683. : outer_allocator_type(other.outer_allocator()) \
  684. , m_inner(other.inner_allocator()) \
  685. {} \
  686. \
  687. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
  688. : outer_allocator_type(::boost::move(other.outer_allocator())) \
  689. , m_inner(::boost::move(other.inner_allocator())) \
  690. {} \
  691. \
  692. template <class OuterA2> \
  693. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base<OuterA2, true \
  694. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  695. BOOST_PP_ENUM_TRAILING \
  696. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  697. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  698. >& other) \
  699. : outer_allocator_type(other.outer_allocator()) \
  700. , m_inner(other.inner_allocator()) \
  701. {} \
  702. \
  703. template <class OuterA2> \
  704. scoped_allocator_adaptor_base \
  705. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true \
  706. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  707. BOOST_PP_ENUM_TRAILING \
  708. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  709. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  710. > BOOST_RV_REF_END other) \
  711. : outer_allocator_type(other.outer_allocator()) \
  712. , m_inner(other.inner_allocator()) \
  713. {} \
  714. \
  715. public: \
  716. struct internal_type_t{}; \
  717. \
  718. template <class OuterA2> \
  719. scoped_allocator_adaptor_base \
  720. ( internal_type_t \
  721. , BOOST_FWD_REF(OuterA2) outerAlloc \
  722. , const inner_allocator_type &inner) \
  723. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
  724. , m_inner(inner) \
  725. {} \
  726. \
  727. public: \
  728. scoped_allocator_adaptor_base &operator= \
  729. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) \
  730. { \
  731. outer_allocator_type::operator=(other.outer_allocator()); \
  732. m_inner = other.inner_allocator(); \
  733. return *this; \
  734. } \
  735. \
  736. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
  737. { \
  738. outer_allocator_type::operator=(boost::move(other.outer_allocator())); \
  739. m_inner = ::boost::move(other.inner_allocator()); \
  740. return *this; \
  741. } \
  742. \
  743. void swap(scoped_allocator_adaptor_base &r) \
  744. { \
  745. boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); \
  746. boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); \
  747. } \
  748. \
  749. friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) \
  750. { l.swap(r); } \
  751. \
  752. inner_allocator_type& inner_allocator() \
  753. { return m_inner; } \
  754. \
  755. inner_allocator_type const& inner_allocator() const \
  756. { return m_inner; } \
  757. \
  758. outer_allocator_type & outer_allocator() \
  759. { return static_cast<outer_allocator_type&>(*this); } \
  760. \
  761. const outer_allocator_type &outer_allocator() const \
  762. { return static_cast<const outer_allocator_type&>(*this); } \
  763. \
  764. scoped_allocator_type select_on_container_copy_construction() const \
  765. { \
  766. return scoped_allocator_type \
  767. (internal_type_t() \
  768. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) \
  769. ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) \
  770. ); \
  771. } \
  772. private: \
  773. inner_allocator_type m_inner; \
  774. }; \
  775. //!
  776. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  777. #include BOOST_PP_LOCAL_ITERATE()
  778. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  779. //Specialization for adaptor without any InnerAlloc
  780. template <typename OuterAlloc>
  781. class scoped_allocator_adaptor_base
  782. < OuterAlloc
  783. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  784. , true
  785. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat)
  786. #endif
  787. >
  788. : public OuterAlloc
  789. {
  790. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
  791. public:
  792. template <class U>
  793. struct rebind_base
  794. {
  795. typedef scoped_allocator_adaptor_base
  796. <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
  797. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  798. , true
  799. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  800. #endif
  801. > other;
  802. };
  803. typedef OuterAlloc outer_allocator_type;
  804. typedef allocator_traits<OuterAlloc> outer_traits_type;
  805. typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
  806. typedef inner_allocator_type scoped_allocator_type;
  807. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  808. typedef typename outer_traits_type::
  809. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  810. typedef typename outer_traits_type::
  811. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  812. typedef typename outer_traits_type::
  813. propagate_on_container_swap propagate_on_container_swap;
  814. scoped_allocator_adaptor_base()
  815. {}
  816. template <class OuterA2>
  817. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
  818. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  819. {}
  820. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  821. : outer_allocator_type(other.outer_allocator())
  822. {}
  823. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  824. : outer_allocator_type(::boost::move(other.outer_allocator()))
  825. {}
  826. template <class OuterA2>
  827. scoped_allocator_adaptor_base
  828. (const scoped_allocator_adaptor_base<
  829. OuterA2
  830. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  831. , true
  832. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  833. #endif
  834. >& other)
  835. : outer_allocator_type(other.outer_allocator())
  836. {}
  837. template <class OuterA2>
  838. scoped_allocator_adaptor_base
  839. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<
  840. OuterA2
  841. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  842. , true
  843. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  844. #endif
  845. > BOOST_RV_REF_END other)
  846. : outer_allocator_type(other.outer_allocator())
  847. {}
  848. public:
  849. struct internal_type_t{};
  850. template <class OuterA2>
  851. scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
  852. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  853. {}
  854. public:
  855. scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  856. {
  857. outer_allocator_type::operator=(other.outer_allocator());
  858. return *this;
  859. }
  860. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  861. {
  862. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  863. return *this;
  864. }
  865. void swap(scoped_allocator_adaptor_base &r)
  866. {
  867. boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
  868. }
  869. friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
  870. { l.swap(r); }
  871. inner_allocator_type& inner_allocator()
  872. { return static_cast<inner_allocator_type&>(*this); }
  873. inner_allocator_type const& inner_allocator() const
  874. { return static_cast<const inner_allocator_type&>(*this); }
  875. outer_allocator_type & outer_allocator()
  876. { return static_cast<outer_allocator_type&>(*this); }
  877. const outer_allocator_type &outer_allocator() const
  878. { return static_cast<const outer_allocator_type&>(*this); }
  879. scoped_allocator_type select_on_container_copy_construction() const
  880. {
  881. return scoped_allocator_type
  882. (internal_type_t()
  883. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
  884. //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
  885. //as inner_allocator() is equal to *this and that would trigger an infinite loop
  886. , this->inner_allocator()
  887. );
  888. }
  889. };
  890. } //namespace container_detail {
  891. ///@endcond
  892. //Scoped allocator
  893. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  894. #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  895. //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor.
  896. //! The class template scoped_allocator_adaptor is an allocator template that specifies
  897. //! the memory resource (the outer allocator) to be used by a container (as any other
  898. //! allocator does) and also specifies an inner allocator resource to be passed to
  899. //! the constructor of every element within the container.
  900. //!
  901. //! This adaptor is
  902. //! instantiated with one outer and zero or more inner allocator types. If
  903. //! instantiated with only one allocator type, the inner allocator becomes the
  904. //! scoped_allocator_adaptor itself, thus using the same allocator resource for the
  905. //! container and every element within the container and, if the elements themselves
  906. //! are containers, each of their elements recursively. If instantiated with more than
  907. //! one allocator, the first allocator is the outer allocator for use by the container,
  908. //! the second allocator is passed to the constructors of the container's elements,
  909. //! and, if the elements themselves are containers, the third allocator is passed to
  910. //! the elements' elements, and so on. If containers are nested to a depth greater
  911. //! than the number of allocators, the last allocator is used repeatedly, as in the
  912. //! single-allocator case, for any remaining recursions.
  913. //!
  914. //! [<b>Note</b>: The
  915. //! scoped_allocator_adaptor is derived from the outer allocator type so it can be
  916. //! substituted for the outer allocator type in most expressions. -end note]
  917. //!
  918. //! In the construct member functions, `OUTERMOST(x)` is x if x does not have
  919. //! an `outer_allocator()` member function and
  920. //! `OUTERMOST(x.outer_allocator())` otherwise; `OUTERMOST_ALLOC_TRAITS(x)` is
  921. //! `allocator_traits<decltype(OUTERMOST(x))>`.
  922. //!
  923. //! [<b>Note</b>: `OUTERMOST(x)` and
  924. //! `OUTERMOST_ALLOC_TRAITS(x)` are recursive operations. It is incumbent upon
  925. //! the definition of `outer_allocator()` to ensure that the recursion terminates.
  926. //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note]
  927. template <typename OuterAlloc, typename ...InnerAllocs>
  928. class scoped_allocator_adaptor
  929. #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  930. template <typename OuterAlloc, typename ...InnerAllocs>
  931. class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
  932. #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  933. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  934. template <typename OuterAlloc
  935. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  936. >
  937. class scoped_allocator_adaptor
  938. #endif
  939. : public container_detail::scoped_allocator_adaptor_base
  940. <OuterAlloc
  941. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  942. , InnerAllocs...
  943. #else
  944. , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  945. #endif
  946. >
  947. {
  948. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
  949. public:
  950. /// @cond
  951. typedef container_detail::scoped_allocator_adaptor_base
  952. <OuterAlloc
  953. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  954. , InnerAllocs...
  955. #else
  956. , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  957. #endif
  958. > base_type;
  959. typedef typename base_type::internal_type_t internal_type_t;
  960. /// @endcond
  961. typedef OuterAlloc outer_allocator_type;
  962. //! Type: For exposition only
  963. //!
  964. typedef allocator_traits<OuterAlloc> outer_traits_type;
  965. //! Type: `scoped_allocator_adaptor<OuterAlloc>` if `sizeof...(InnerAllocs)` is zero; otherwise,
  966. //! `scoped_allocator_adaptor<InnerAllocs...>`.
  967. typedef typename base_type::inner_allocator_type inner_allocator_type;
  968. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  969. typedef typename outer_traits_type::value_type value_type;
  970. typedef typename outer_traits_type::size_type size_type;
  971. typedef typename outer_traits_type::difference_type difference_type;
  972. typedef typename outer_traits_type::pointer pointer;
  973. typedef typename outer_traits_type::const_pointer const_pointer;
  974. typedef typename outer_traits_type::void_pointer void_pointer;
  975. typedef typename outer_traits_type::const_void_pointer const_void_pointer;
  976. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value` is
  977. //! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  978. typedef typename base_type::
  979. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  980. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_move_assignment::value` is
  981. //! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  982. typedef typename base_type::
  983. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  984. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_swap::value` is true for any
  985. //! `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  986. typedef typename base_type::
  987. propagate_on_container_swap propagate_on_container_swap;
  988. //! Type: Rebinds scoped allocator to
  989. //! `typedef scoped_allocator_adaptor
  990. //! < typename outer_traits_type::template portable_rebind_alloc<U>::type
  991. //! , InnerAllocs... >`
  992. template <class U>
  993. struct rebind
  994. {
  995. typedef scoped_allocator_adaptor
  996. < typename outer_traits_type::template portable_rebind_alloc<U>::type
  997. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  998. , InnerAllocs...
  999. #else
  1000. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1001. #endif
  1002. > other;
  1003. };
  1004. //! <b>Effects</b>: value-initializes the OuterAlloc base class
  1005. //! and the inner allocator object.
  1006. scoped_allocator_adaptor()
  1007. {}
  1008. ~scoped_allocator_adaptor()
  1009. {}
  1010. //! <b>Effects</b>: initializes each allocator within the adaptor with
  1011. //! the corresponding allocator from other.
  1012. scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
  1013. : base_type(other.base())
  1014. {}
  1015. //! <b>Effects</b>: move constructs each allocator within the adaptor with
  1016. //! the corresponding allocator from other.
  1017. scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
  1018. : base_type(::boost::move(other.base()))
  1019. {}
  1020. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1021. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  1022. //!
  1023. //! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
  1024. //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
  1025. //! corresponding allocator from the argument list).
  1026. template <class OuterA2>
  1027. scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
  1028. : base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
  1029. {}
  1030. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1031. #define BOOST_PP_LOCAL_MACRO(n) \
  1032. template <class OuterA2> \
  1033. scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc \
  1034. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
  1035. : base_type(::boost::forward<OuterA2>(outerAlloc) \
  1036. BOOST_PP_ENUM_TRAILING_PARAMS(n, q) \
  1037. ) \
  1038. {} \
  1039. //!
  1040. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  1041. #include BOOST_PP_LOCAL_ITERATE()
  1042. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1043. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  1044. //!
  1045. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other.
  1046. template <class OuterA2>
  1047. scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2
  1048. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1049. , InnerAllocs...
  1050. #else
  1051. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1052. #endif
  1053. > &other)
  1054. : base_type(other.base())
  1055. {}
  1056. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  1057. //!
  1058. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator
  1059. //! rvalue from other.
  1060. template <class OuterA2>
  1061. scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor<OuterA2
  1062. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1063. , InnerAllocs...
  1064. #else
  1065. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1066. #endif
  1067. > BOOST_RV_REF_END other)
  1068. : base_type(::boost::move(other.base()))
  1069. {}
  1070. scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
  1071. { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(static_cast<const base_type &>(other))); }
  1072. scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other)
  1073. { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(static_cast<base_type&>(other)))); }
  1074. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  1075. //! <b>Effects</b>: swaps *this with r.
  1076. //!
  1077. void swap(scoped_allocator_adaptor &r);
  1078. //! <b>Effects</b>: swaps *this with r.
  1079. //!
  1080. friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
  1081. //! <b>Returns</b>:
  1082. //! `static_cast<OuterAlloc&>(*this)`.
  1083. outer_allocator_type & outer_allocator();
  1084. //! <b>Returns</b>:
  1085. //! `static_cast<const OuterAlloc&>(*this)`.
  1086. const outer_allocator_type &outer_allocator() const;
  1087. //! <b>Returns</b>:
  1088. //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
  1089. inner_allocator_type& inner_allocator();
  1090. //! <b>Returns</b>:
  1091. //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
  1092. inner_allocator_type const& inner_allocator() const;
  1093. #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
  1094. //! <b>Returns</b>:
  1095. //! `allocator_traits<OuterAlloc>::max_size(outer_allocator())`.
  1096. size_type max_size() const
  1097. {
  1098. return outer_traits_type::max_size(this->outer_allocator());
  1099. }
  1100. //! <b>Effects</b>:
  1101. //! calls `OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)`.
  1102. template <class T>
  1103. void destroy(T* p)
  1104. {
  1105. allocator_traits<typename outermost_allocator<OuterAlloc>::type>
  1106. ::destroy(get_outermost_allocator(this->outer_allocator()), p);
  1107. }
  1108. //! <b>Returns</b>:
  1109. //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)`.
  1110. pointer allocate(size_type n)
  1111. {
  1112. return outer_traits_type::allocate(this->outer_allocator(), n);
  1113. }
  1114. //! <b>Returns</b>:
  1115. //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)`.
  1116. pointer allocate(size_type n, const_void_pointer hint)
  1117. {
  1118. return outer_traits_type::allocate(this->outer_allocator(), n, hint);
  1119. }
  1120. //! <b>Effects</b>:
  1121. //! `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)`.
  1122. void deallocate(pointer p, size_type n)
  1123. {
  1124. outer_traits_type::deallocate(this->outer_allocator(), p, n);
  1125. }
  1126. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  1127. //! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator
  1128. //! A in the adaptor is initialized from the result of calling
  1129. //! `allocator_traits<Allocator>::select_on_container_copy_construction()` on
  1130. //! the corresponding allocator in *this.
  1131. scoped_allocator_adaptor select_on_container_copy_construction() const;
  1132. #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
  1133. /// @cond
  1134. base_type &base() { return *this; }
  1135. const base_type &base() const { return *this; }
  1136. /// @endcond
  1137. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1138. //! <b>Effects</b>:
  1139. //! 1) If `uses_allocator<T, inner_allocator_type>::value` is false calls
  1140. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct
  1141. //! (OUTERMOST(*this), p, std::forward<Args>(args)...)`.
  1142. //!
  1143. //! 2) Otherwise, if `uses_allocator<T, inner_allocator_type>::value` is true and
  1144. //! `is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value` is true, calls
  1145. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
  1146. //! inner_allocator(), std::forward<Args>(args)...)`.
  1147. //!
  1148. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, `is_constructible` can't
  1149. //! be implemented so that condition will be replaced by
  1150. //! constructible_with_allocator_prefix<T>::value. -end note]
  1151. //!
  1152. //! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
  1153. //! `is_constructible<T, Args..., inner_allocator_type>::value` is true, calls
  1154. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
  1155. //! std::forward<Args>(args)..., inner_allocator())`.
  1156. //!
  1157. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, `is_constructible` can't be
  1158. //! implemented so that condition will be replaced by
  1159. //! `constructible_with_allocator_suffix<T>::value`. -end note]
  1160. //!
  1161. //! 4) Otherwise, the program is ill-formed.
  1162. //!
  1163. //! [<b>Note</b>: An error will result if `uses_allocator` evaluates
  1164. //! to true but the specific constructor does not take an allocator. This definition prevents a silent
  1165. //! failure to pass an inner allocator to a contained element. -end note]
  1166. template < typename T, class ...Args>
  1167. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1168. void
  1169. #else
  1170. typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type
  1171. #endif
  1172. construct(T* p, BOOST_FWD_REF(Args)...args)
  1173. {
  1174. container_detail::dispatch_uses_allocator
  1175. ( uses_allocator<T, inner_allocator_type>()
  1176. , get_outermost_allocator(this->outer_allocator())
  1177. , this->inner_allocator()
  1178. , p, ::boost::forward<Args>(args)...);
  1179. }
  1180. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1181. //Disable this overload if the first argument is pair as some compilers have
  1182. //overload selection problems when the first parameter is a pair.
  1183. #define BOOST_PP_LOCAL_MACRO(n) \
  1184. template < typename T \
  1185. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  1186. > \
  1187. typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type \
  1188. construct(T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  1189. { \
  1190. container_detail::dispatch_uses_allocator \
  1191. ( uses_allocator<T, inner_allocator_type>() \
  1192. , get_outermost_allocator(this->outer_allocator()) \
  1193. , this->inner_allocator() \
  1194. , p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
  1195. } \
  1196. //!
  1197. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  1198. #include BOOST_PP_LOCAL_ITERATE()
  1199. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1200. template <class T1, class T2>
  1201. void construct(std::pair<T1,T2>* p)
  1202. { this->construct_pair(p); }
  1203. template <class T1, class T2>
  1204. void construct(container_detail::pair<T1,T2>* p)
  1205. { this->construct_pair(p); }
  1206. template <class T1, class T2, class U, class V>
  1207. void construct(std::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1208. { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
  1209. template <class T1, class T2, class U, class V>
  1210. void construct(container_detail::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1211. { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
  1212. template <class T1, class T2, class U, class V>
  1213. void construct(std::pair<T1, T2>* p, const std::pair<U, V>& x)
  1214. { this->construct_pair(p, x); }
  1215. template <class T1, class T2, class U, class V>
  1216. void construct( container_detail::pair<T1, T2>* p
  1217. , const container_detail::pair<U, V>& x)
  1218. { this->construct_pair(p, x); }
  1219. template <class T1, class T2, class U, class V>
  1220. void construct( std::pair<T1, T2>* p
  1221. , BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
  1222. { this->construct_pair(p, x); }
  1223. template <class T1, class T2, class U, class V>
  1224. void construct( container_detail::pair<T1, T2>* p
  1225. , BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
  1226. { this->construct_pair(p, x); }
  1227. /// @cond
  1228. private:
  1229. template <class Pair>
  1230. void construct_pair(Pair* p)
  1231. {
  1232. this->construct(container_detail::addressof(p->first));
  1233. BOOST_TRY{
  1234. this->construct(container_detail::addressof(p->second));
  1235. }
  1236. BOOST_CATCH(...){
  1237. this->destroy(container_detail::addressof(p->first));
  1238. BOOST_RETHROW
  1239. }
  1240. BOOST_CATCH_END
  1241. }
  1242. template <class Pair, class U, class V>
  1243. void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1244. {
  1245. this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
  1246. BOOST_TRY{
  1247. this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
  1248. }
  1249. BOOST_CATCH(...){
  1250. this->destroy(container_detail::addressof(p->first));
  1251. BOOST_RETHROW
  1252. }
  1253. BOOST_CATCH_END
  1254. }
  1255. template <class Pair, class Pair2>
  1256. void construct_pair(Pair* p, const Pair2& pr)
  1257. {
  1258. this->construct(container_detail::addressof(p->first), pr.first);
  1259. BOOST_TRY{
  1260. this->construct(container_detail::addressof(p->second), pr.second);
  1261. }
  1262. BOOST_CATCH(...){
  1263. this->destroy(container_detail::addressof(p->first));
  1264. BOOST_RETHROW
  1265. }
  1266. BOOST_CATCH_END
  1267. }
  1268. template <class Pair, class Pair2>
  1269. void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
  1270. {
  1271. this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
  1272. BOOST_TRY{
  1273. this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
  1274. }
  1275. BOOST_CATCH(...){
  1276. this->destroy(container_detail::addressof(p->first));
  1277. BOOST_RETHROW
  1278. }
  1279. BOOST_CATCH_END
  1280. }
  1281. //template <class T1, class T2, class... Args1, class... Args2>
  1282. //void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
  1283. public:
  1284. //Internal function
  1285. template <class OuterA2>
  1286. scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
  1287. : base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
  1288. {}
  1289. /// @endcond
  1290. };
  1291. template <typename OuterA1, typename OuterA2
  1292. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1293. , typename... InnerAllocs
  1294. #else
  1295. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  1296. #endif
  1297. >
  1298. inline bool operator==(
  1299. const scoped_allocator_adaptor<OuterA1
  1300. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1301. ,InnerAllocs...
  1302. #else
  1303. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1304. #endif
  1305. >& a,
  1306. const scoped_allocator_adaptor<OuterA2
  1307. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1308. ,InnerAllocs...
  1309. #else
  1310. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1311. #endif
  1312. >& b)
  1313. {
  1314. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1315. const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
  1316. #else
  1317. const bool has_zero_inner =
  1318. boost::container::container_detail::is_same
  1319. <Q0, container_detail::nat>::value;
  1320. #endif
  1321. return a.outer_allocator() == b.outer_allocator()
  1322. && (has_zero_inner || a.inner_allocator() == b.inner_allocator());
  1323. }
  1324. template <typename OuterA1, typename OuterA2
  1325. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1326. , typename... InnerAllocs
  1327. #else
  1328. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  1329. #endif
  1330. >
  1331. inline bool operator!=(
  1332. const scoped_allocator_adaptor<OuterA1
  1333. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1334. ,InnerAllocs...
  1335. #else
  1336. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1337. #endif
  1338. >& a,
  1339. const scoped_allocator_adaptor<OuterA2
  1340. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1341. ,InnerAllocs...
  1342. #else
  1343. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1344. #endif
  1345. >& b)
  1346. {
  1347. return ! (a == b);
  1348. }
  1349. }} // namespace boost { namespace container {
  1350. #include <boost/container/detail/config_end.hpp>
  1351. #endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP