PageRenderTime 30ms CodeModel.GetById 34ms 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

Large files files are truncated, but you can click here to view the full file

  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 allo…

Large files files are truncated, but you can click here to view the full file