PageRenderTime 29ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/External/boost/boost/container/scoped_allocator.hpp

http://klayge.codeplex.com
C++ Header | 1470 lines | 1000 code | 173 blank | 297 comment | 29 complexity | ffbb1f9cab21788ef52046b3180bd951 MD5 | raw file
Possible License(s): MIT, LGPL-2.1, Unlicense, BSD-3-Clause
  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) && (_MSC_VER >= 1200)
  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 boost::integral_constant<
  514. bool,
  515. outer_traits_type::propagate_on_container_copy_assignment::value ||
  516. inner_allocator_type::propagate_on_container_copy_assignment::value
  517. > propagate_on_container_copy_assignment;
  518. typedef boost::integral_constant<
  519. bool,
  520. outer_traits_type::propagate_on_container_move_assignment::value ||
  521. inner_allocator_type::propagate_on_container_move_assignment::value
  522. > propagate_on_container_move_assignment;
  523. typedef boost::integral_constant<
  524. bool,
  525. outer_traits_type::propagate_on_container_swap::value ||
  526. inner_allocator_type::propagate_on_container_swap::value
  527. > propagate_on_container_swap;
  528. scoped_allocator_adaptor_base()
  529. {}
  530. template <class OuterA2>
  531. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
  532. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  533. , m_inner(args...)
  534. {}
  535. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  536. : outer_allocator_type(other.outer_allocator())
  537. , m_inner(other.inner_allocator())
  538. {}
  539. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  540. : outer_allocator_type(::boost::move(other.outer_allocator()))
  541. , m_inner(::boost::move(other.inner_allocator()))
  542. {}
  543. template <class OuterA2>
  544. scoped_allocator_adaptor_base
  545. (const scoped_allocator_adaptor_base<OuterA2, InnerAllocs...>& other)
  546. : outer_allocator_type(other.outer_allocator())
  547. , m_inner(other.inner_allocator())
  548. {}
  549. template <class OuterA2>
  550. scoped_allocator_adaptor_base
  551. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base
  552. <OuterA2, InnerAllocs...> BOOST_RV_REF_END other)
  553. : outer_allocator_type(other.outer_allocator())
  554. , m_inner(other.inner_allocator())
  555. {}
  556. protected:
  557. struct internal_type_t{};
  558. template <class OuterA2>
  559. scoped_allocator_adaptor_base
  560. ( internal_type_t
  561. , BOOST_FWD_REF(OuterA2) outerAlloc
  562. , const inner_allocator_type &inner)
  563. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  564. , m_inner(inner)
  565. {}
  566. public:
  567. scoped_allocator_adaptor_base &operator=
  568. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  569. {
  570. outer_allocator_type::operator=(other.outer_allocator());
  571. m_inner = other.inner_allocator();
  572. return *this;
  573. }
  574. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  575. {
  576. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  577. m_inner = ::boost::move(other.inner_allocator());
  578. return *this;
  579. }
  580. inner_allocator_type& inner_allocator()
  581. { return m_inner; }
  582. inner_allocator_type const& inner_allocator() const
  583. { return m_inner; }
  584. outer_allocator_type & outer_allocator()
  585. { return static_cast<outer_allocator_type&>(*this); }
  586. const outer_allocator_type &outer_allocator() const
  587. { return static_cast<const outer_allocator_type&>(*this); }
  588. private:
  589. inner_allocator_type m_inner;
  590. };
  591. #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  592. //Let's add a dummy first template parameter to allow creating
  593. //specializations up to maximum InnerAlloc count
  594. template <
  595. typename OuterAlloc
  596. , bool Dummy
  597. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  598. >
  599. class scoped_allocator_adaptor_base;
  600. //Specializations for the adaptor with InnerAlloc allocators
  601. #define BOOST_PP_LOCAL_MACRO(n) \
  602. template <typename OuterAlloc \
  603. BOOST_PP_ENUM_TRAILING_PARAMS(n, class Q) \
  604. > \
  605. class scoped_allocator_adaptor_base<OuterAlloc, true \
  606. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  607. BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  608. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  609. > \
  610. : public OuterAlloc \
  611. { \
  612. typedef allocator_traits<OuterAlloc> outer_traits_type; \
  613. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) \
  614. \
  615. public: \
  616. template <class OuterA2> \
  617. struct rebind_base \
  618. { \
  619. typedef scoped_allocator_adaptor_base<OuterA2, true BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  620. BOOST_PP_ENUM_TRAILING \
  621. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  622. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  623. > other; \
  624. }; \
  625. \
  626. typedef OuterAlloc outer_allocator_type; \
  627. typedef scoped_allocator_adaptor<BOOST_PP_ENUM_PARAMS(n, Q) \
  628. BOOST_PP_ENUM_TRAILING \
  629. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  630. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  631. > inner_allocator_type; \
  632. typedef boost::integral_constant< \
  633. bool, \
  634. outer_traits_type::propagate_on_container_copy_assignment::value || \
  635. inner_allocator_type::propagate_on_container_copy_assignment::value \
  636. > propagate_on_container_copy_assignment; \
  637. typedef boost::integral_constant< \
  638. bool, \
  639. outer_traits_type::propagate_on_container_move_assignment::value || \
  640. inner_allocator_type::propagate_on_container_move_assignment::value \
  641. > propagate_on_container_move_assignment; \
  642. typedef boost::integral_constant< \
  643. bool, \
  644. outer_traits_type::propagate_on_container_swap::value || \
  645. inner_allocator_type::propagate_on_container_swap::value \
  646. > propagate_on_container_swap; \
  647. \
  648. scoped_allocator_adaptor_base() \
  649. {} \
  650. \
  651. template <class OuterA2> \
  652. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc \
  653. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
  654. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
  655. , m_inner(BOOST_PP_ENUM_PARAMS(n, q)) \
  656. {} \
  657. \
  658. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) \
  659. : outer_allocator_type(other.outer_allocator()) \
  660. , m_inner(other.inner_allocator()) \
  661. {} \
  662. \
  663. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
  664. : outer_allocator_type(::boost::move(other.outer_allocator())) \
  665. , m_inner(::boost::move(other.inner_allocator())) \
  666. {} \
  667. \
  668. template <class OuterA2> \
  669. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base<OuterA2, true \
  670. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  671. BOOST_PP_ENUM_TRAILING \
  672. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  673. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  674. >& other) \
  675. : outer_allocator_type(other.outer_allocator()) \
  676. , m_inner(other.inner_allocator()) \
  677. {} \
  678. \
  679. template <class OuterA2> \
  680. scoped_allocator_adaptor_base \
  681. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true \
  682. BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
  683. BOOST_PP_ENUM_TRAILING \
  684. ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
  685. , BOOST_CONTAINER_PP_IDENTITY, nat) \
  686. > BOOST_RV_REF_END other) \
  687. : outer_allocator_type(other.outer_allocator()) \
  688. , m_inner(other.inner_allocator()) \
  689. {} \
  690. \
  691. protected: \
  692. struct internal_type_t{}; \
  693. \
  694. template <class OuterA2> \
  695. scoped_allocator_adaptor_base \
  696. ( internal_type_t \
  697. , BOOST_FWD_REF(OuterA2) outerAlloc \
  698. , const inner_allocator_type &inner) \
  699. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
  700. , m_inner(inner) \
  701. {} \
  702. \
  703. public: \
  704. scoped_allocator_adaptor_base &operator= \
  705. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) \
  706. { \
  707. outer_allocator_type::operator=(other.outer_allocator()); \
  708. m_inner = other.inner_allocator(); \
  709. return *this; \
  710. } \
  711. \
  712. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
  713. { \
  714. outer_allocator_type::operator=(boost::move(other.outer_allocator())); \
  715. m_inner = ::boost::move(other.inner_allocator()); \
  716. return *this; \
  717. } \
  718. \
  719. inner_allocator_type& inner_allocator() \
  720. { return m_inner; } \
  721. \
  722. inner_allocator_type const& inner_allocator() const \
  723. { return m_inner; } \
  724. \
  725. outer_allocator_type & outer_allocator() \
  726. { return static_cast<outer_allocator_type&>(*this); } \
  727. \
  728. const outer_allocator_type &outer_allocator() const \
  729. { return static_cast<const outer_allocator_type&>(*this); } \
  730. \
  731. private: \
  732. inner_allocator_type m_inner; \
  733. }; \
  734. //!
  735. #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  736. #include BOOST_PP_LOCAL_ITERATE()
  737. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  738. //Specialization for adaptor without any InnerAlloc
  739. template <typename OuterAlloc>
  740. class scoped_allocator_adaptor_base
  741. < OuterAlloc
  742. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  743. , true
  744. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat)
  745. #endif
  746. >
  747. : public OuterAlloc
  748. {
  749. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
  750. public:
  751. template <class U>
  752. struct rebind_base
  753. {
  754. typedef scoped_allocator_adaptor_base
  755. <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
  756. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  757. , true
  758. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  759. #endif
  760. > other;
  761. };
  762. typedef OuterAlloc outer_allocator_type;
  763. typedef allocator_traits<OuterAlloc> outer_traits_type;
  764. typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
  765. typedef typename outer_traits_type::
  766. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  767. typedef typename outer_traits_type::
  768. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  769. typedef typename outer_traits_type::
  770. propagate_on_container_swap propagate_on_container_swap;
  771. scoped_allocator_adaptor_base()
  772. {}
  773. template <class OuterA2>
  774. scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
  775. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  776. {}
  777. scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  778. : outer_allocator_type(other.outer_allocator())
  779. {}
  780. scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  781. : outer_allocator_type(::boost::move(other.outer_allocator()))
  782. {}
  783. template <class OuterA2>
  784. scoped_allocator_adaptor_base
  785. (const scoped_allocator_adaptor_base<
  786. OuterA2
  787. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  788. , true
  789. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  790. #endif
  791. >& other)
  792. : outer_allocator_type(other.outer_allocator())
  793. {}
  794. template <class OuterA2>
  795. scoped_allocator_adaptor_base
  796. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<
  797. OuterA2
  798. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  799. , true
  800. BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
  801. #endif
  802. > BOOST_RV_REF_END other)
  803. : outer_allocator_type(other.outer_allocator())
  804. {}
  805. protected:
  806. struct internal_type_t{};
  807. template <class OuterA2>
  808. scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
  809. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  810. {}
  811. public:
  812. scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  813. {
  814. outer_allocator_type::operator=(other.outer_allocator());
  815. return *this;
  816. }
  817. scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  818. {
  819. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  820. return *this;
  821. }
  822. inner_allocator_type& inner_allocator()
  823. { return static_cast<inner_allocator_type&>(*this); }
  824. inner_allocator_type const& inner_allocator() const
  825. { return static_cast<const inner_allocator_type&>(*this); }
  826. outer_allocator_type & outer_allocator()
  827. { return static_cast<outer_allocator_type&>(*this); }
  828. const outer_allocator_type &outer_allocator() const
  829. { return static_cast<const outer_allocator_type&>(*this); }
  830. };
  831. } //namespace container_detail {
  832. ///@endcond
  833. //Scoped allocator
  834. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  835. #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  836. //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor.
  837. //! The class template scoped_allocator_adaptor is an allocator template that specifies
  838. //! the memory resource (the outer allocator) to be used by a container (as any other
  839. //! allocator does) and also specifies an inner allocator resource to be passed to
  840. //! the constructor of every element within the container.
  841. //!
  842. //! This adaptor is
  843. //! instantiated with one outer and zero or more inner allocator types. If
  844. //! instantiated with only one allocator type, the inner allocator becomes the
  845. //! scoped_allocator_adaptor itself, thus using the same allocator resource for the
  846. //! container and every element within the container and, if the elements themselves
  847. //! are containers, each of their elements recursively. If instantiated with more than
  848. //! one allocator, the first allocator is the outer allocator for use by the container,
  849. //! the second allocator is passed to the constructors of the container's elements,
  850. //! and, if the elements themselves are containers, the third allocator is passed to
  851. //! the elements' elements, and so on. If containers are nested to a depth greater
  852. //! than the number of allocators, the last allocator is used repeatedly, as in the
  853. //! single-allocator case, for any remaining recursions.
  854. //!
  855. //! [<b>Note</b>: The
  856. //! scoped_allocator_adaptor is derived from the outer allocator type so it can be
  857. //! substituted for the outer allocator type in most expressions. -end note]
  858. //!
  859. //! In the construct member functions, `OUTERMOST(x)` is x if x does not have
  860. //! an `outer_allocator()` member function and
  861. //! `OUTERMOST(x.outer_allocator())` otherwise; `OUTERMOST_ALLOC_TRAITS(x)` is
  862. //! `allocator_traits<decltype(OUTERMOST(x))>`.
  863. //!
  864. //! [<b>Note</b>: `OUTERMOST(x)` and
  865. //! `OUTERMOST_ALLOC_TRAITS(x)` are recursive operations. It is incumbent upon
  866. //! the definition of `outer_allocator()` to ensure that the recursion terminates.
  867. //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note]
  868. template <typename OuterAlloc, typename ...InnerAllocs>
  869. class scoped_allocator_adaptor
  870. #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  871. template <typename OuterAlloc, typename ...InnerAllocs>
  872. class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
  873. #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  874. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  875. template <typename OuterAlloc
  876. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  877. >
  878. class scoped_allocator_adaptor
  879. #endif
  880. : public container_detail::scoped_allocator_adaptor_base
  881. <OuterAlloc
  882. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  883. , InnerAllocs...
  884. #else
  885. , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  886. #endif
  887. >
  888. {
  889. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
  890. public:
  891. /// @cond
  892. typedef container_detail::scoped_allocator_adaptor_base
  893. <OuterAlloc
  894. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  895. , InnerAllocs...
  896. #else
  897. , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  898. #endif
  899. > base_type;
  900. typedef typename base_type::internal_type_t internal_type_t;
  901. /// @endcond
  902. typedef OuterAlloc outer_allocator_type;
  903. //! Type: For exposition only
  904. //!
  905. typedef allocator_traits<OuterAlloc> outer_traits_type;
  906. //! Type: `scoped_allocator_adaptor<OuterAlloc>` if `sizeof...(InnerAllocs)` is zero; otherwise,
  907. //! `scoped_allocator_adaptor<InnerAllocs...>`.
  908. typedef typename base_type::inner_allocator_type inner_allocator_type;
  909. typedef typename outer_traits_type::value_type value_type;
  910. typedef typename outer_traits_type::size_type size_type;
  911. typedef typename outer_traits_type::difference_type difference_type;
  912. typedef typename outer_traits_type::pointer pointer;
  913. typedef typename outer_traits_type::const_pointer const_pointer;
  914. typedef typename outer_traits_type::void_pointer void_pointer;
  915. typedef typename outer_traits_type::const_void_pointer const_void_pointer;
  916. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_copy_assignment::value` is
  917. //! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  918. typedef typename base_type::
  919. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  920. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_move_assignment::value` is
  921. //! true for any `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  922. typedef typename base_type::
  923. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  924. //! Type: `true_type` if `allocator_traits<Allocator>::propagate_on_container_swap::value` is true for any
  925. //! `Allocator` in the set of `OuterAlloc` and `InnerAllocs...`; otherwise, false_type.
  926. typedef typename base_type::
  927. propagate_on_container_swap propagate_on_container_swap;
  928. //! Type: Rebinds scoped allocator to
  929. //! `typedef scoped_allocator_adaptor
  930. //! < typename outer_traits_type::template portable_rebind_alloc<U>::type
  931. //! , InnerAllocs... >`
  932. template <class U>
  933. struct rebind
  934. {
  935. typedef scoped_allocator_adaptor
  936. < typename outer_traits_type::template portable_rebind_alloc<U>::type
  937. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  938. , InnerAllocs...
  939. #else
  940. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  941. #endif
  942. > other;
  943. };
  944. //! <b>Effects</b>: value-initializes the OuterAlloc base class
  945. //! and the inner allocator object.
  946. scoped_allocator_adaptor()
  947. {}
  948. ~scoped_allocator_adaptor()
  949. {}
  950. //! <b>Effects</b>: initializes each allocator within the adaptor with
  951. //! the corresponding allocator from other.
  952. scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
  953. : base_type(other.base())
  954. {}
  955. //! <b>Effects</b>: move constructs each allocator within the adaptor with
  956. //! the corresponding allocator from other.
  957. scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
  958. : base_type(::boost::move(other.base()))
  959. {}
  960. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  961. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  962. //!
  963. //! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
  964. //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
  965. //! corresponding allocator from the argument list).
  966. template <class OuterA2>
  967. scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
  968. : base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
  969. {}
  970. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  971. #define BOOST_PP_LOCAL_MACRO(n) \
  972. template <class OuterA2> \
  973. scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc \
  974. BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
  975. : base_type(::boost::forward<OuterA2>(outerAlloc) \
  976. BOOST_PP_ENUM_TRAILING_PARAMS(n, q) \
  977. ) \
  978. {} \
  979. //!
  980. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  981. #include BOOST_PP_LOCAL_ITERATE()
  982. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  983. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  984. //!
  985. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other.
  986. template <class OuterA2>
  987. scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2
  988. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  989. , InnerAllocs...
  990. #else
  991. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  992. #endif
  993. > &other)
  994. : base_type(other.base())
  995. {}
  996. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  997. //!
  998. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator
  999. //! rvalue from other.
  1000. template <class OuterA2>
  1001. scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor<OuterA2
  1002. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1003. , InnerAllocs...
  1004. #else
  1005. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1006. #endif
  1007. > BOOST_RV_REF_END other)
  1008. : base_type(::boost::move(other.base()))
  1009. {}
  1010. scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
  1011. {
  1012. base_type::operator=(static_cast<const base_type &>(other));
  1013. return *this;
  1014. }
  1015. scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other)
  1016. {
  1017. base_type::operator=(boost::move(static_cast<scoped_allocator_adaptor&>(other)));
  1018. return *this;
  1019. }
  1020. //! <b>Returns</b>:
  1021. //! `static_cast<OuterAlloc&>(*this)`.
  1022. outer_allocator_type & outer_allocator()
  1023. { return *this; }
  1024. //! <b>Returns</b>:
  1025. //! `static_cast<const OuterAlloc&>(*this)`.
  1026. const outer_allocator_type &outer_allocator() const
  1027. { return *this; }
  1028. //! <b>Returns</b>:
  1029. //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
  1030. inner_allocator_type& inner_allocator()
  1031. { return base_type::inner_allocator(); }
  1032. //! <b>Returns</b>:
  1033. //! *this if `sizeof...(InnerAllocs)` is zero; otherwise, inner.
  1034. inner_allocator_type const& inner_allocator() const
  1035. { return base_type::inner_allocator(); }
  1036. //! <b>Returns</b>:
  1037. //! `allocator_traits<OuterAlloc>::max_size(outer_allocator())`.
  1038. size_type max_size() const
  1039. {
  1040. return outer_traits_type::max_size(this->outer_allocator());
  1041. }
  1042. //! <b>Effects</b>:
  1043. //! calls `OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)`.
  1044. template <class T>
  1045. void destroy(T* p)
  1046. {
  1047. allocator_traits<typename outermost_allocator<OuterAlloc>::type>
  1048. ::destroy(get_outermost_allocator(this->outer_allocator()), p);
  1049. }
  1050. //! <b>Returns</b>:
  1051. //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)`.
  1052. pointer allocate(size_type n)
  1053. {
  1054. return outer_traits_type::allocate(this->outer_allocator(), n);
  1055. }
  1056. //! <b>Returns</b>:
  1057. //! `allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)`.
  1058. pointer allocate(size_type n, const_void_pointer hint)
  1059. {
  1060. return outer_traits_type::allocate(this->outer_allocator(), n, hint);
  1061. }
  1062. //! <b>Effects</b>:
  1063. //! `allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)`.
  1064. void deallocate(pointer p, size_type n)
  1065. {
  1066. outer_traits_type::deallocate(this->outer_allocator(), p, n);
  1067. }
  1068. //! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator
  1069. //! A in the adaptor is initialized from the result of calling
  1070. //! `allocator_traits<Allocator>::select_on_container_copy_construction()` on
  1071. //! the corresponding allocator in *this.
  1072. scoped_allocator_adaptor select_on_container_copy_construction() const
  1073. {
  1074. return scoped_allocator_adaptor
  1075. (internal_type_t()
  1076. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
  1077. ,outer_traits_type::select_on_container_copy_construction(this->inner_allocator())
  1078. );
  1079. }
  1080. /// @cond
  1081. base_type &base() { return *this; }
  1082. const base_type &base() const { return *this; }
  1083. /// @endcond
  1084. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1085. //! <b>Effects</b>:
  1086. //! 1) If `uses_allocator<T, inner_allocator_type>::value` is false calls
  1087. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct
  1088. //! (OUTERMOST(*this), p, std::forward<Args>(args)...)`.
  1089. //!
  1090. //! 2) Otherwise, if `uses_allocator<T, inner_allocator_type>::value` is true and
  1091. //! `is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value` is true, calls
  1092. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
  1093. //! inner_allocator(), std::forward<Args>(args)...)`.
  1094. //!
  1095. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, `is_constructible` can't
  1096. //! be implemented so that condition will be replaced by
  1097. //! constructible_with_allocator_prefix<T>::value. -end note]
  1098. //!
  1099. //! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
  1100. //! `is_constructible<T, Args..., inner_allocator_type>::value` is true, calls
  1101. //! `OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
  1102. //! std::forward<Args>(args)..., inner_allocator())`.
  1103. //!
  1104. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, `is_constructible` can't be
  1105. //! implemented so that condition will be replaced by
  1106. //! `constructible_with_allocator_suffix<T>::value`. -end note]
  1107. //!
  1108. //! 4) Otherwise, the program is ill-formed.
  1109. //!
  1110. //! [<b>Note</b>: An error will result if `uses_allocator` evaluates
  1111. //! to true but the specific constructor does not take an allocator. This definition prevents a silent
  1112. //! failure to pass an inner allocator to a contained element. -end note]
  1113. template < typename T, class ...Args>
  1114. #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1115. void
  1116. #else
  1117. typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type
  1118. #endif
  1119. construct(T* p, BOOST_FWD_REF(Args)...args)
  1120. {
  1121. container_detail::dispatch_uses_allocator
  1122. ( uses_allocator<T, inner_allocator_type>()
  1123. , get_outermost_allocator(this->outer_allocator())
  1124. , this->inner_allocator()
  1125. , p, ::boost::forward<Args>(args)...);
  1126. }
  1127. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1128. //Disable this overload if the first argument is pair as some compilers have
  1129. //overload selection problems when the first parameter is a pair.
  1130. #define BOOST_PP_LOCAL_MACRO(n) \
  1131. template < typename T \
  1132. BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
  1133. > \
  1134. typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type \
  1135. construct(T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
  1136. { \
  1137. container_detail::dispatch_uses_allocator \
  1138. ( uses_allocator<T, inner_allocator_type>() \
  1139. , get_outermost_allocator(this->outer_allocator()) \
  1140. , this->inner_allocator() \
  1141. , p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
  1142. } \
  1143. //!
  1144. #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
  1145. #include BOOST_PP_LOCAL_ITERATE()
  1146. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1147. template <class T1, class T2>
  1148. void construct(std::pair<T1,T2>* p)
  1149. { this->construct_pair(p); }
  1150. template <class T1, class T2>
  1151. void construct(container_detail::pair<T1,T2>* p)
  1152. { this->construct_pair(p); }
  1153. template <class T1, class T2, class U, class V>
  1154. void construct(std::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1155. { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
  1156. template <class T1, class T2, class U, class V>
  1157. void construct(container_detail::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1158. { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
  1159. template <class T1, class T2, class U, class V>
  1160. void construct(std::pair<T1, T2>* p, const std::pair<U, V>& x)
  1161. { this->construct_pair(p, x); }
  1162. template <class T1, class T2, class U, class V>
  1163. void construct( container_detail::pair<T1, T2>* p
  1164. , const container_detail::pair<U, V>& x)
  1165. { this->construct_pair(p, x); }
  1166. template <class T1, class T2, class U, class V>
  1167. void construct( std::pair<T1, T2>* p
  1168. , BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
  1169. { this->construct_pair(p, x); }
  1170. template <class T1, class T2, class U, class V>
  1171. void construct( container_detail::pair<T1, T2>* p
  1172. , BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
  1173. { this->construct_pair(p, x); }
  1174. /// @cond
  1175. private:
  1176. template <class Pair>
  1177. void construct_pair(Pair* p)
  1178. {
  1179. this->construct(container_detail::addressof(p->first));
  1180. BOOST_TRY{
  1181. this->construct(container_detail::addressof(p->second));
  1182. }
  1183. BOOST_CATCH(...){
  1184. this->destroy(container_detail::addressof(p->first));
  1185. BOOST_RETHROW
  1186. }
  1187. BOOST_CATCH_END
  1188. }
  1189. template <class Pair, class U, class V>
  1190. void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
  1191. {
  1192. this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
  1193. BOOST_TRY{
  1194. this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
  1195. }
  1196. BOOST_CATCH(...){
  1197. this->destroy(container_detail::addressof(p->first));
  1198. BOOST_RETHROW
  1199. }
  1200. BOOST_CATCH_END
  1201. }
  1202. template <class Pair, class Pair2>
  1203. void construct_pair(Pair* p, const Pair2& pr)
  1204. {
  1205. this->construct(container_detail::addressof(p->first), pr.first);
  1206. BOOST_TRY{
  1207. this->construct(container_detail::addressof(p->second), pr.second);
  1208. }
  1209. BOOST_CATCH(...){
  1210. this->destroy(container_detail::addressof(p->first));
  1211. BOOST_RETHROW
  1212. }
  1213. BOOST_CATCH_END
  1214. }
  1215. template <class Pair, class Pair2>
  1216. void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
  1217. {
  1218. this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
  1219. BOOST_TRY{
  1220. this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
  1221. }
  1222. BOOST_CATCH(...){
  1223. this->destroy(container_detail::addressof(p->first));
  1224. BOOST_RETHROW
  1225. }
  1226. BOOST_CATCH_END
  1227. }
  1228. //template <class T1, class T2, class... Args1, class... Args2>
  1229. //void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
  1230. private:
  1231. template <class OuterA2>
  1232. scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
  1233. : base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
  1234. {}
  1235. /// @endcond
  1236. };
  1237. template <typename OuterA1, typename OuterA2
  1238. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1239. , typename... InnerAllocs
  1240. #else
  1241. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  1242. #endif
  1243. >
  1244. inline bool operator==(
  1245. const scoped_allocator_adaptor<OuterA1
  1246. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1247. ,InnerAllocs...
  1248. #else
  1249. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1250. #endif
  1251. >& a,
  1252. const scoped_allocator_adaptor<OuterA2
  1253. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1254. ,InnerAllocs...
  1255. #else
  1256. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1257. #endif
  1258. >& b)
  1259. {
  1260. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1261. const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
  1262. #else
  1263. const bool has_zero_inner =
  1264. boost::container::container_detail::is_same
  1265. <Q0, container_detail::nat>::value;
  1266. #endif
  1267. return a.outer_allocator() == b.outer_allocator()
  1268. && (has_zero_inner || a.inner_allocator() == b.inner_allocator());
  1269. }
  1270. template <typename OuterA1, typename OuterA2
  1271. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1272. , typename... InnerAllocs
  1273. #else
  1274. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
  1275. #endif
  1276. >
  1277. inline bool operator!=(
  1278. const scoped_allocator_adaptor<OuterA1
  1279. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1280. ,InnerAllocs...
  1281. #else
  1282. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1283. #endif
  1284. >& a,
  1285. const scoped_allocator_adaptor<OuterA2
  1286. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  1287. ,InnerAllocs...
  1288. #else
  1289. BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
  1290. #endif
  1291. >& b)
  1292. {
  1293. return ! (a == b);
  1294. }
  1295. }} // namespace boost { namespace container {
  1296. #include <boost/container/detail/config_end.hpp>
  1297. #endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP