scoped_allocator.hpp 36 KB

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