scoped_allocator.hpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905
  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-2013. Distributed under the Boost
  10. // Software License, Version 1.0. (See accompanying file
  11. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // See http://www.boost.org/libs/container for documentation.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
  17. #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
  18. #if defined (_MSC_VER)
  19. # pragma once
  20. #endif
  21. #include <boost/container/detail/config_begin.hpp>
  22. #include <boost/container/detail/workaround.hpp>
  23. #include <boost/container/allocator_traits.hpp>
  24. #include <boost/container/scoped_allocator_fwd.hpp>
  25. #include <boost/container/detail/dispatch_uses_allocator.hpp>
  26. #include <boost/container/detail/mpl.hpp>
  27. #include <boost/container/detail/pair.hpp>
  28. #include <boost/container/detail/type_traits.hpp>
  29. #include <boost/move/adl_move_swap.hpp>
  30. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  31. #include <boost/move/detail/fwd_macros.hpp>
  32. #endif
  33. #include <boost/move/utility_core.hpp>
  34. namespace boost { namespace container {
  35. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  36. namespace dtl {
  37. template <typename Allocator>
  38. struct is_scoped_allocator_imp
  39. {
  40. typedef char yes_type;
  41. struct no_type{ char dummy[2]; };
  42. template <typename T>
  43. static yes_type test(typename T::outer_allocator_type*);
  44. template <typename T>
  45. static int test(...);
  46. static const bool value = (sizeof(yes_type) == sizeof(test<Allocator>(0)));
  47. };
  48. template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
  49. struct outermost_allocator_type_impl
  50. {
  51. typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
  52. typedef typename outermost_allocator_type_impl<outer_type>::type type;
  53. };
  54. template<class MaybeScopedAlloc>
  55. struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
  56. {
  57. typedef MaybeScopedAlloc type;
  58. };
  59. template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
  60. struct outermost_allocator_imp
  61. {
  62. typedef MaybeScopedAlloc type;
  63. inline static type &get(MaybeScopedAlloc &a)
  64. { return a; }
  65. inline static const type &get(const MaybeScopedAlloc &a)
  66. { return a; }
  67. };
  68. template<class MaybeScopedAlloc>
  69. struct outermost_allocator_imp<MaybeScopedAlloc, true>
  70. {
  71. typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
  72. typedef typename outermost_allocator_type_impl<outer_type>::type type;
  73. inline static type &get(MaybeScopedAlloc &a)
  74. { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
  75. inline static const type &get(const MaybeScopedAlloc &a)
  76. { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
  77. };
  78. } //namespace dtl {
  79. template <typename Allocator>
  80. struct is_scoped_allocator
  81. : dtl::is_scoped_allocator_imp<Allocator>
  82. {};
  83. template <typename Allocator>
  84. struct outermost_allocator
  85. : dtl::outermost_allocator_imp<Allocator>
  86. {};
  87. template <typename Allocator>
  88. inline typename outermost_allocator<Allocator>::type &
  89. get_outermost_allocator(Allocator &a)
  90. { return outermost_allocator<Allocator>::get(a); }
  91. template <typename Allocator>
  92. inline const typename outermost_allocator<Allocator>::type &
  93. get_outermost_allocator(const Allocator &a)
  94. { return outermost_allocator<Allocator>::get(a); }
  95. namespace dtl {
  96. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  97. template <typename OuterAlloc, class ...InnerAllocs>
  98. class scoped_allocator_adaptor_base
  99. : public OuterAlloc
  100. {
  101. typedef allocator_traits<OuterAlloc> outer_traits_type;
  102. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
  103. public:
  104. template <class OuterA2>
  105. struct rebind_base
  106. {
  107. typedef scoped_allocator_adaptor_base<OuterA2, InnerAllocs...> other;
  108. };
  109. typedef OuterAlloc outer_allocator_type;
  110. typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
  111. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  112. typedef scoped_allocator_adaptor
  113. <OuterAlloc, InnerAllocs...> scoped_allocator_type;
  114. typedef dtl::bool_<
  115. outer_traits_type::propagate_on_container_copy_assignment::value ||
  116. inner_allocator_type::propagate_on_container_copy_assignment::value
  117. > propagate_on_container_copy_assignment;
  118. typedef dtl::bool_<
  119. outer_traits_type::propagate_on_container_move_assignment::value ||
  120. inner_allocator_type::propagate_on_container_move_assignment::value
  121. > propagate_on_container_move_assignment;
  122. typedef dtl::bool_<
  123. outer_traits_type::propagate_on_container_swap::value ||
  124. inner_allocator_type::propagate_on_container_swap::value
  125. > propagate_on_container_swap;
  126. typedef dtl::bool_<
  127. outer_traits_type::is_always_equal::value &&
  128. inner_allocator_type::is_always_equal::value
  129. > is_always_equal;
  130. inline scoped_allocator_adaptor_base()
  131. {}
  132. template <class OuterA2>
  133. inline scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
  134. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  135. , m_inner(args...)
  136. {}
  137. inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  138. : outer_allocator_type(other.outer_allocator())
  139. , m_inner(other.inner_allocator())
  140. {}
  141. inline scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  142. : outer_allocator_type(::boost::move(other.outer_allocator()))
  143. , m_inner(::boost::move(other.inner_allocator()))
  144. {}
  145. template <class OuterA2>
  146. inline scoped_allocator_adaptor_base
  147. (const scoped_allocator_adaptor_base<OuterA2, InnerAllocs...>& other)
  148. : outer_allocator_type(other.outer_allocator())
  149. , m_inner(other.inner_allocator())
  150. {}
  151. template <class OuterA2>
  152. inline scoped_allocator_adaptor_base
  153. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base
  154. <OuterA2, InnerAllocs...> BOOST_RV_REF_END other)
  155. : outer_allocator_type(other.outer_allocator())
  156. , m_inner(other.inner_allocator())
  157. {}
  158. public:
  159. struct internal_type_t{};
  160. template <class OuterA2>
  161. inline scoped_allocator_adaptor_base
  162. ( internal_type_t
  163. , BOOST_FWD_REF(OuterA2) outerAlloc
  164. , const inner_allocator_type &inner)
  165. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  166. , m_inner(inner)
  167. {}
  168. public:
  169. inline scoped_allocator_adaptor_base &operator=
  170. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  171. {
  172. outer_allocator_type::operator=(other.outer_allocator());
  173. m_inner = other.inner_allocator();
  174. return *this;
  175. }
  176. inline scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  177. {
  178. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  179. m_inner = ::boost::move(other.inner_allocator());
  180. return *this;
  181. }
  182. inline void swap(scoped_allocator_adaptor_base &r)
  183. {
  184. boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
  185. boost::adl_move_swap(this->m_inner, r.inner_allocator());
  186. }
  187. inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
  188. { l.swap(r); }
  189. inline inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW
  190. { return m_inner; }
  191. inline inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
  192. { return m_inner; }
  193. inline outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW
  194. { return static_cast<outer_allocator_type&>(*this); }
  195. inline const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW
  196. { return static_cast<const outer_allocator_type&>(*this); }
  197. inline scoped_allocator_type select_on_container_copy_construction() const
  198. {
  199. return scoped_allocator_type
  200. (internal_type_t()
  201. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
  202. ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
  203. );
  204. }
  205. private:
  206. inner_allocator_type m_inner;
  207. };
  208. #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  209. //Let's add a dummy first template parameter to allow creating
  210. //specializations up to maximum InnerAlloc count
  211. template <typename OuterAlloc, bool Dummy, BOOST_MOVE_CLASSDFLT9>
  212. class scoped_allocator_adaptor_base;
  213. //Specializations for the adaptor with InnerAlloc allocators
  214. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE(N)\
  215. template <typename OuterAlloc BOOST_MOVE_I##N BOOST_MOVE_CLASS##N>\
  216. class scoped_allocator_adaptor_base<OuterAlloc, true, BOOST_MOVE_TARG##N>\
  217. : public OuterAlloc\
  218. {\
  219. typedef allocator_traits<OuterAlloc> outer_traits_type;\
  220. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)\
  221. \
  222. public:\
  223. template <class OuterA2>\
  224. struct rebind_base\
  225. {\
  226. typedef scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> other;\
  227. };\
  228. \
  229. typedef OuterAlloc outer_allocator_type;\
  230. typedef scoped_allocator_adaptor<BOOST_MOVE_TARG##N> inner_allocator_type;\
  231. typedef scoped_allocator_adaptor<OuterAlloc, BOOST_MOVE_TARG##N> scoped_allocator_type;\
  232. typedef allocator_traits<inner_allocator_type> inner_traits_type;\
  233. typedef dtl::bool_<\
  234. outer_traits_type::propagate_on_container_copy_assignment::value ||\
  235. inner_allocator_type::propagate_on_container_copy_assignment::value\
  236. > propagate_on_container_copy_assignment;\
  237. typedef dtl::bool_<\
  238. outer_traits_type::propagate_on_container_move_assignment::value ||\
  239. inner_allocator_type::propagate_on_container_move_assignment::value\
  240. > propagate_on_container_move_assignment;\
  241. typedef dtl::bool_<\
  242. outer_traits_type::propagate_on_container_swap::value ||\
  243. inner_allocator_type::propagate_on_container_swap::value\
  244. > propagate_on_container_swap;\
  245. \
  246. typedef dtl::bool_<\
  247. outer_traits_type::is_always_equal::value &&\
  248. inner_allocator_type::is_always_equal::value\
  249. > is_always_equal;\
  250. \
  251. inline scoped_allocator_adaptor_base(){}\
  252. \
  253. template <class OuterA2>\
  254. inline scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, BOOST_MOVE_CREF##N)\
  255. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\
  256. , m_inner(BOOST_MOVE_ARG##N)\
  257. {}\
  258. \
  259. inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)\
  260. : outer_allocator_type(other.outer_allocator())\
  261. , m_inner(other.inner_allocator())\
  262. {}\
  263. \
  264. inline scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\
  265. : outer_allocator_type(::boost::move(other.outer_allocator()))\
  266. , m_inner(::boost::move(other.inner_allocator()))\
  267. {}\
  268. \
  269. template <class OuterA2>\
  270. inline scoped_allocator_adaptor_base\
  271. (const scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N>& other)\
  272. : outer_allocator_type(other.outer_allocator())\
  273. , m_inner(other.inner_allocator())\
  274. {}\
  275. \
  276. template <class OuterA2>\
  277. inline scoped_allocator_adaptor_base\
  278. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true, BOOST_MOVE_TARG##N> BOOST_RV_REF_END other)\
  279. : outer_allocator_type(other.outer_allocator())\
  280. , m_inner(other.inner_allocator())\
  281. {}\
  282. \
  283. public:\
  284. struct internal_type_t{};\
  285. \
  286. template <class OuterA2>\
  287. inline scoped_allocator_adaptor_base\
  288. ( internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &inner)\
  289. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))\
  290. , m_inner(inner)\
  291. {}\
  292. \
  293. public:\
  294. inline scoped_allocator_adaptor_base &operator=\
  295. (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)\
  296. {\
  297. outer_allocator_type::operator=(other.outer_allocator());\
  298. m_inner = other.inner_allocator();\
  299. return *this;\
  300. }\
  301. \
  302. inline scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)\
  303. {\
  304. outer_allocator_type::operator=(boost::move(other.outer_allocator()));\
  305. m_inner = ::boost::move(other.inner_allocator());\
  306. return *this;\
  307. }\
  308. \
  309. inline void swap(scoped_allocator_adaptor_base &r)\
  310. {\
  311. boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());\
  312. boost::adl_move_swap(this->m_inner, r.inner_allocator());\
  313. }\
  314. \
  315. inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)\
  316. { l.swap(r); }\
  317. \
  318. inline inner_allocator_type& inner_allocator()\
  319. { return m_inner; }\
  320. \
  321. inline inner_allocator_type const& inner_allocator() const\
  322. { return m_inner; }\
  323. \
  324. inline outer_allocator_type & outer_allocator()\
  325. { return static_cast<outer_allocator_type&>(*this); }\
  326. \
  327. inline const outer_allocator_type &outer_allocator() const\
  328. { return static_cast<const outer_allocator_type&>(*this); }\
  329. \
  330. inline scoped_allocator_type select_on_container_copy_construction() const\
  331. {\
  332. return scoped_allocator_type\
  333. (internal_type_t()\
  334. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())\
  335. ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())\
  336. );\
  337. }\
  338. private:\
  339. inner_allocator_type m_inner;\
  340. };\
  341. //!
  342. BOOST_MOVE_ITERATE_1TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE)
  343. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_BASE_CODE
  344. #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
  345. #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  346. #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE ,true
  347. #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER BOOST_MOVE_TARG9
  348. #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS BOOST_MOVE_CLASS9
  349. #else
  350. #define BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE
  351. #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNER InnerAllocs...
  352. #define BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS typename... InnerAllocs
  353. #endif
  354. //Specialization for adaptor without any InnerAlloc
  355. template <typename OuterAlloc>
  356. class scoped_allocator_adaptor_base< OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>
  357. : public OuterAlloc
  358. {
  359. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
  360. public:
  361. template <class U>
  362. struct rebind_base
  363. {
  364. typedef scoped_allocator_adaptor_base
  365. <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
  366. BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE > other;
  367. };
  368. typedef OuterAlloc outer_allocator_type;
  369. typedef allocator_traits<OuterAlloc> outer_traits_type;
  370. typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
  371. typedef inner_allocator_type scoped_allocator_type;
  372. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  373. typedef typename outer_traits_type::
  374. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  375. typedef typename outer_traits_type::
  376. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  377. typedef typename outer_traits_type::
  378. propagate_on_container_swap propagate_on_container_swap;
  379. typedef typename outer_traits_type::
  380. is_always_equal is_always_equal;
  381. inline scoped_allocator_adaptor_base()
  382. {}
  383. template <class OuterA2>
  384. inline scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
  385. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  386. {}
  387. inline scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
  388. : outer_allocator_type(other.outer_allocator())
  389. {}
  390. inline scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  391. : outer_allocator_type(::boost::move(other.outer_allocator()))
  392. {}
  393. template <class OuterA2>
  394. inline scoped_allocator_adaptor_base
  395. (const scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE>& other)
  396. : outer_allocator_type(other.outer_allocator())
  397. {}
  398. template <class OuterA2>
  399. inline scoped_allocator_adaptor_base
  400. (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2 BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE> BOOST_RV_REF_END other)
  401. : outer_allocator_type(other.outer_allocator())
  402. {}
  403. public:
  404. struct internal_type_t{};
  405. template <class OuterA2>
  406. inline scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
  407. : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
  408. {}
  409. public:
  410. inline scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
  411. {
  412. outer_allocator_type::operator=(other.outer_allocator());
  413. return *this;
  414. }
  415. inline scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
  416. {
  417. outer_allocator_type::operator=(boost::move(other.outer_allocator()));
  418. return *this;
  419. }
  420. inline void swap(scoped_allocator_adaptor_base &r)
  421. {
  422. boost::adl_move_swap(this->outer_allocator(), r.outer_allocator());
  423. }
  424. inline friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
  425. { l.swap(r); }
  426. inline inner_allocator_type& inner_allocator()
  427. { return static_cast<inner_allocator_type&>(*this); }
  428. inline inner_allocator_type const& inner_allocator() const
  429. { return static_cast<const inner_allocator_type&>(*this); }
  430. inline outer_allocator_type & outer_allocator()
  431. { return static_cast<outer_allocator_type&>(*this); }
  432. inline const outer_allocator_type &outer_allocator() const
  433. { return static_cast<const outer_allocator_type&>(*this); }
  434. inline scoped_allocator_type select_on_container_copy_construction() const
  435. {
  436. return scoped_allocator_type
  437. (internal_type_t()
  438. ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
  439. //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
  440. //as inner_allocator() is equal to *this and that would trigger an infinite loop
  441. , this->inner_allocator()
  442. );
  443. }
  444. };
  445. } //namespace dtl {
  446. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  447. //Scoped allocator
  448. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  449. #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  450. //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor.
  451. //! The class template scoped_allocator_adaptor is an allocator template that specifies
  452. //! the memory resource (the outer allocator) to be used by a container (as any other
  453. //! allocator does) and also specifies an inner allocator resource to be passed to
  454. //! the constructor of every element within the container.
  455. //!
  456. //! This adaptor is
  457. //! instantiated with one outer and zero or more inner allocator types. If
  458. //! instantiated with only one allocator type, the inner allocator becomes the
  459. //! scoped_allocator_adaptor itself, thus using the same allocator resource for the
  460. //! container and every element within the container and, if the elements themselves
  461. //! are containers, each of their elements recursively. If instantiated with more than
  462. //! one allocator, the first allocator is the outer allocator for use by the container,
  463. //! the second allocator is passed to the constructors of the container's elements,
  464. //! and, if the elements themselves are containers, the third allocator is passed to
  465. //! the elements' elements, and so on. If containers are nested to a depth greater
  466. //! than the number of allocators, the last allocator is used repeatedly, as in the
  467. //! single-allocator case, for any remaining recursions.
  468. //!
  469. //! [<b>Note</b>: The
  470. //! scoped_allocator_adaptor is derived from the outer allocator type so it can be
  471. //! substituted for the outer allocator type in most expressions. -end note]
  472. //!
  473. //! In the construct member functions, <code>OUTERMOST(x)</code> is x if x does not have
  474. //! an <code>outer_allocator()</code> member function and
  475. //! <code>OUTERMOST(x.outer_allocator())</code> otherwise; <code>OUTERMOST_ALLOC_TRAITS(x)</code> is
  476. //! <code>allocator_traits<decltype(OUTERMOST(x))></code>.
  477. //!
  478. //! [<b>Note</b>: <code>OUTERMOST(x)</code> and
  479. //! <code>OUTERMOST_ALLOC_TRAITS(x)</code> are recursive operations. It is incumbent upon
  480. //! the definition of <code>outer_allocator()</code> to ensure that the recursion terminates.
  481. //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note]
  482. template <typename OuterAlloc, typename ...InnerAllocs>
  483. class scoped_allocator_adaptor
  484. #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  485. template <typename OuterAlloc, typename ...InnerAllocs>
  486. class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
  487. #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
  488. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  489. template <typename OuterAlloc, BOOST_MOVE_CLASS9>
  490. class scoped_allocator_adaptor
  491. #endif
  492. : public dtl::scoped_allocator_adaptor_base
  493. <OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>
  494. {
  495. BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
  496. public:
  497. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  498. typedef dtl::scoped_allocator_adaptor_base
  499. <OuterAlloc BOOST_CONTAINER_SCOPEDALLOC_DUMMYTRUE, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> base_type;
  500. typedef typename base_type::internal_type_t internal_type_t;
  501. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  502. typedef OuterAlloc outer_allocator_type;
  503. //! Type: For exposition only
  504. //!
  505. typedef allocator_traits<OuterAlloc> outer_traits_type;
  506. //! Type: <code>scoped_allocator_adaptor<OuterAlloc></code> if <code>sizeof...(InnerAllocs)</code> is zero; otherwise,
  507. //! <code>scoped_allocator_adaptor<InnerAllocs...></code>.
  508. typedef typename base_type::inner_allocator_type inner_allocator_type;
  509. typedef allocator_traits<inner_allocator_type> inner_traits_type;
  510. typedef typename outer_traits_type::value_type value_type;
  511. typedef typename outer_traits_type::size_type size_type;
  512. typedef typename outer_traits_type::difference_type difference_type;
  513. typedef typename outer_traits_type::pointer pointer;
  514. typedef typename outer_traits_type::const_pointer const_pointer;
  515. typedef typename outer_traits_type::void_pointer void_pointer;
  516. typedef typename outer_traits_type::const_void_pointer const_void_pointer;
  517. //! Type: A type with a constant boolean <code>value</code> == true if
  518. //!`allocator_traits<Allocator>:: propagate_on_container_copy_assignment::value` is
  519. //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
  520. typedef typename base_type::
  521. propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
  522. //! Type: A type with a constant boolean <code>value</code> == true if
  523. //!`allocator_traits<Allocator>:: propagate_on_container_move_assignment::value` is
  524. //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
  525. typedef typename base_type::
  526. propagate_on_container_move_assignment propagate_on_container_move_assignment;
  527. //! Type: A type with a constant boolean <code>value</code> == true if
  528. //! `allocator_traits<Allocator>:: propagate_on_container_swap::value` is
  529. //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
  530. typedef typename base_type::
  531. propagate_on_container_swap propagate_on_container_swap;
  532. //! Type: A type with a constant boolean <code>value</code> == true if
  533. //!`allocator_traits<Allocator>:: is_always_equal::value` is
  534. //! true for all <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>, false otherwise.
  535. typedef typename base_type::
  536. is_always_equal is_always_equal;
  537. //! Type: Rebinds scoped allocator to
  538. //! <code>typedef scoped_allocator_adaptor
  539. //! < typename outer_traits_type::template portable_rebind_alloc<U>::type
  540. //! , InnerAllocs... ></code>
  541. template <class U>
  542. struct rebind
  543. {
  544. typedef scoped_allocator_adaptor
  545. < typename outer_traits_type::template portable_rebind_alloc<U>::type
  546. , BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> other;
  547. };
  548. //! <b>Effects</b>: value-initializes the OuterAlloc base class
  549. //! and the inner allocator object.
  550. inline scoped_allocator_adaptor()
  551. {}
  552. inline ~scoped_allocator_adaptor()
  553. {}
  554. //! <b>Effects</b>: initializes each allocator within the adaptor with
  555. //! the corresponding allocator from other.
  556. inline scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
  557. : base_type(other.base())
  558. {}
  559. //! <b>Effects</b>: move constructs each allocator within the adaptor with
  560. //! the corresponding allocator from other.
  561. inline scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
  562. : base_type(::boost::move(other.base()))
  563. {}
  564. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  565. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  566. //!
  567. //! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
  568. //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
  569. //! corresponding allocator from the argument list).
  570. template <class OuterA2>
  571. inline scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
  572. : base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
  573. {}
  574. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  575. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE(N)\
  576. template <class OuterA2>\
  577. inline scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc BOOST_MOVE_I##N BOOST_MOVE_CREF##N)\
  578. : base_type(::boost::forward<OuterA2>(outerAlloc) BOOST_MOVE_I##N BOOST_MOVE_ARG##N)\
  579. {}\
  580. //
  581. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE)
  582. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_ADAPTOR_RELATED_ALLOCATOR_CONSTRUCTOR_CODE
  583. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  584. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  585. //!
  586. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other.
  587. template <class OuterA2>
  588. inline scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> &other)
  589. : base_type(other.base())
  590. {}
  591. //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
  592. //!
  593. //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator
  594. //! rvalue from other.
  595. template <class OuterA2>
  596. inline scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor
  597. <OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER> BOOST_RV_REF_END other)
  598. : base_type(::boost::move(other.base()))
  599. {}
  600. inline scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
  601. { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(static_cast<const base_type &>(other))); }
  602. inline scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other)
  603. { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(other.base()))); }
  604. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  605. //! <b>Effects</b>: swaps *this with r.
  606. //!
  607. void swap(scoped_allocator_adaptor &r);
  608. //! <b>Effects</b>: swaps *this with r.
  609. //!
  610. friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
  611. //! <b>Returns</b>:
  612. //! <code>static_cast<OuterAlloc&>(*this)</code>.
  613. outer_allocator_type & outer_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
  614. //! <b>Returns</b>:
  615. //! <code>static_cast<const OuterAlloc&>(*this)</code>.
  616. const outer_allocator_type &outer_allocator() const BOOST_NOEXCEPT_OR_NOTHROW;
  617. //! <b>Returns</b>:
  618. //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
  619. inner_allocator_type& inner_allocator() BOOST_NOEXCEPT_OR_NOTHROW;
  620. //! <b>Returns</b>:
  621. //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
  622. inner_allocator_type const& inner_allocator() const BOOST_NOEXCEPT_OR_NOTHROW;
  623. #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
  624. //! <b>Returns</b>:
  625. //! <code>allocator_traits<OuterAlloc>:: max_size(outer_allocator())</code>.
  626. inline size_type max_size() const BOOST_NOEXCEPT_OR_NOTHROW
  627. { return outer_traits_type::max_size(this->outer_allocator()); }
  628. //! <b>Effects</b>:
  629. //! calls <code>OUTERMOST_ALLOC_TRAITS(*this):: destroy(OUTERMOST(*this), p)</code>.
  630. template <class T>
  631. inline void destroy(T* p) BOOST_NOEXCEPT_OR_NOTHROW
  632. {
  633. allocator_traits<typename outermost_allocator<OuterAlloc>::type>
  634. ::destroy(get_outermost_allocator(this->outer_allocator()), p);
  635. }
  636. //! <b>Returns</b>:
  637. //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
  638. inline pointer allocate(size_type n)
  639. { return outer_traits_type::allocate(this->outer_allocator(), n); }
  640. //! <b>Returns</b>:
  641. //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
  642. inline pointer allocate(size_type n, const_void_pointer hint)
  643. { return outer_traits_type::allocate(this->outer_allocator(), n, hint); }
  644. //! <b>Effects</b>:
  645. //! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>.
  646. inline void deallocate(pointer p, size_type n)
  647. { outer_traits_type::deallocate(this->outer_allocator(), p, n); }
  648. #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
  649. //! <b>Returns</b>: A new scoped_allocator_adaptor object where each allocator
  650. //! Allocator in the adaptor is initialized from the result of calling
  651. //! <code>allocator_traits<Allocator>::select_on_container_copy_construction()</code> on
  652. //! the corresponding allocator in *this.
  653. scoped_allocator_adaptor select_on_container_copy_construction() const;
  654. #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
  655. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  656. inline base_type &base() { return *this; }
  657. inline const base_type &base() const { return *this; }
  658. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  659. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  660. //! <b>Effects</b>:
  661. //! 1) If <code>uses_allocator<T, inner_allocator_type>::value</code> is false calls
  662. //! <code>OUTERMOST_ALLOC_TRAITS(*this)::
  663. //! construct(OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
  664. //!
  665. //! 2) Otherwise, if <code>uses_allocator<T, inner_allocator_type>::value</code> is true and
  666. //! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>:: value</code> is true, calls
  667. //! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p, allocator_arg,
  668. //! inner_allocator(), std::forward<Args>(args)...)</code>.
  669. //!
  670. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't
  671. //! be implemented so that condition will be replaced by
  672. //! constructible_with_allocator_prefix<T>::value. -end note]
  673. //!
  674. //! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
  675. //! <code>is_constructible<T, Args..., inner_allocator_type>:: value</code> is true, calls
  676. //! <code>OUTERMOST_ALLOC_TRAITS(*this):: construct(OUTERMOST(*this), p,
  677. //! std::forward<Args>(args)..., inner_allocator())</code>.
  678. //!
  679. //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't be
  680. //! implemented so that condition will be replaced by
  681. //! <code>constructible_with_allocator_suffix<T>:: value</code>. -end note]
  682. //!
  683. //! 4) Otherwise, the program is ill-formed.
  684. //!
  685. //! [<b>Note</b>: An error will result if <code>uses_allocator</code> evaluates
  686. //! to true but the specific constructor does not take an allocator. This definition prevents a silent
  687. //! failure to pass an inner allocator to a contained element. -end note]
  688. template < typename T, class ...Args>
  689. inline void construct(T* p, BOOST_FWD_REF(Args)...args)
  690. {
  691. dtl::dispatch_uses_allocator
  692. ( (get_outermost_allocator)(this->outer_allocator())
  693. , this->inner_allocator(), p, ::boost::forward<Args>(args)...);
  694. }
  695. #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  696. //Disable this overload if the first argument is pair as some compilers have
  697. //overload selection problems when the first parameter is a pair.
  698. #define BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE(N) \
  699. template < typename T BOOST_MOVE_I##N BOOST_MOVE_CLASSQ##N >\
  700. inline void construct(T* p BOOST_MOVE_I##N BOOST_MOVE_UREFQ##N)\
  701. {\
  702. dtl::dispatch_uses_allocator\
  703. ( (get_outermost_allocator)(this->outer_allocator())\
  704. , this->inner_allocator(), p BOOST_MOVE_I##N BOOST_MOVE_FWDQ##N);\
  705. }\
  706. //
  707. BOOST_MOVE_ITERATE_0TO9(BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE)
  708. #undef BOOST_CONTAINER_SCOPED_ALLOCATOR_CONSTRUCT_CODE
  709. #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  710. #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  711. public:
  712. //Internal function
  713. template <class OuterA2>
  714. inline scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
  715. : base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
  716. {}
  717. #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
  718. };
  719. /// @cond
  720. template<bool ZeroInner>
  721. struct scoped_allocator_operator_equal
  722. {
  723. //Optimize equal outer allocator types with
  724. //allocator_traits::equal which uses is_always_equal
  725. template<class IA>
  726. inline static bool equal_outer(const IA &l, const IA &r)
  727. { return allocator_traits<IA>::equal(l, r); }
  728. //Otherwise compare it normally
  729. template<class IA1, class IA2>
  730. inline static bool equal_outer(const IA1 &l, const IA2 &r)
  731. { return l == r; }
  732. //Otherwise compare it normally
  733. template<class IA>
  734. inline static bool equal_inner(const IA &l, const IA &r)
  735. { return allocator_traits<IA>::equal(l, r); }
  736. };
  737. template<>
  738. struct scoped_allocator_operator_equal<true>
  739. : scoped_allocator_operator_equal<false>
  740. {
  741. //when inner allocator count is zero,
  742. //inner_allocator_type is the same as outer_allocator_type
  743. //so both types can be different in operator==
  744. template<class IA1, class IA2>
  745. inline static bool equal_inner(const IA1 &, const IA2 &)
  746. { return true; }
  747. };
  748. /// @endcond
  749. template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
  750. inline bool operator==(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
  751. ,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
  752. {
  753. #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
  754. const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
  755. #else
  756. const bool has_zero_inner = boost::container::dtl::is_same<P0, void>::value;
  757. #endif
  758. typedef scoped_allocator_operator_equal<has_zero_inner> equal_t;
  759. return equal_t::equal_outer(a.outer_allocator(), b.outer_allocator()) &&
  760. equal_t::equal_inner(a.inner_allocator(), b.inner_allocator());
  761. }
  762. template <typename OuterA1, typename OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNERCLASS>
  763. inline bool operator!=(const scoped_allocator_adaptor<OuterA1, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& a
  764. ,const scoped_allocator_adaptor<OuterA2, BOOST_CONTAINER_SCOPEDALLOC_ALLINNER>& b)
  765. { return !(a == b); }
  766. }} // namespace boost { namespace container {
  767. #include <boost/container/detail/config_end.hpp>
  768. #endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP