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