1 //////////////////////////////////////////////////////////////////////////////
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)
7 //////////////////////////////////////////////////////////////////////////////
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)
13 // See http://www.boost.org/libs/container for documentation.
15 //////////////////////////////////////////////////////////////////////////////
17 #ifndef BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
18 #define BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP
20 #if defined (_MSC_VER)
24 #include <boost/container/detail/config_begin.hpp>
25 #include <boost/container/detail/workaround.hpp>
26 #include <boost/container/scoped_allocator_fwd.hpp>
27 #include <boost/type_traits/integral_constant.hpp>
28 #include <boost/container/allocator_traits.hpp>
29 #include <boost/container/detail/type_traits.hpp>
30 #include <boost/container/detail/utilities.hpp>
32 #include <boost/container/detail/pair.hpp>
33 #include <boost/move/utility_core.hpp>
34 #include <boost/core/no_exceptions_support.hpp>
36 namespace boost { namespace container {
38 //! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed
39 //! with an allocator as its last constructor argument. Ideally, all constructors of T (including the
40 //! copy and move constructors) should have a variant that accepts a final argument of
43 //! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type,
44 //! allocator_type and at least one constructor for which allocator_type is the last
45 //! parameter. If not all constructors of T can be called with a final allocator_type argument,
46 //! and if T is used in a context where a container must call such a constructor, then the program is
50 //! template <class T, class Allocator = allocator<T> >
53 //! typedef Allocator allocator_type;
55 //! // Default constructor with optional allocator suffix
56 //! Z(const allocator_type& a = allocator_type());
58 //! // Copy constructor and allocator-extended copy constructor
60 //! Z(const Z& zz, const allocator_type& a);
63 //! // Specialize trait for class template Z
64 //! template <class T, class Allocator = allocator<T> >
65 //! struct constructible_with_allocator_suffix<Z<T,Allocator> >
66 //! : ::boost::true_type { };
69 //! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
70 //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
71 //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
72 //! Applications aiming portability with several compilers should always define this trait.
74 //! In conforming C++11 compilers or compilers supporting SFINAE expressions
75 //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
76 //! to detect if a type should be constructed with suffix or prefix allocator arguments.
78 struct constructible_with_allocator_suffix
82 //! <b>Remark</b>: if a specialization is derived from true_type, indicates that T may be constructed
83 //! with allocator_arg and T::allocator_type as its first two constructor arguments.
84 //! Ideally, all constructors of T (including the copy and move constructors) should have a variant
85 //! that accepts these two initial arguments.
87 //! <b>Requires</b>: if a specialization is derived from true_type, T must have a nested type,
88 //! allocator_type and at least one constructor for which allocator_arg_t is the first
89 //! parameter and allocator_type is the second parameter. If not all constructors of T can be
90 //! called with these initial arguments, and if T is used in a context where a container must call such
91 //! a constructor, then the program is ill-formed.
94 //! template <class T, class Allocator = allocator<T> >
97 //! typedef Allocator allocator_type;
99 //! // Default constructor with and allocator-extended default constructor
101 //! Y(allocator_arg_t, const allocator_type& a);
103 //! // Copy constructor and allocator-extended copy constructor
105 //! Y(allocator_arg_t, const allocator_type& a, const Y& yy);
107 //! // Variadic constructor and allocator-extended variadic constructor
108 //! template<class ...Args> Y(Args&& args...);
109 //! template<class ...Args>
110 //! Y(allocator_arg_t, const allocator_type& a, Args&&... args);
113 //! // Specialize trait for class template Y
114 //! template <class T, class Allocator = allocator<T> >
115 //! struct constructible_with_allocator_prefix<Y<T,Allocator> >
116 //! : ::boost::true_type { };
120 //! <b>Note</b>: This trait is a workaround inspired by "N2554: The Scoped Allocator Model (Rev 2)"
121 //! (Pablo Halpern, 2008-02-29) to backport the scoped allocator model to C++03, as
122 //! in C++03 there is no mechanism to detect if a type can be constructed from arbitrary arguments.
123 //! Applications aiming portability with several compilers should always define this trait.
125 //! In conforming C++11 compilers or compilers supporting SFINAE expressions
126 //! (when BOOST_NO_SFINAE_EXPR is NOT defined), this trait is ignored and C++11 rules will be used
127 //! to detect if a type should be constructed with suffix or prefix allocator arguments.
129 struct constructible_with_allocator_prefix
130 : ::boost::false_type
133 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
135 namespace container_detail {
137 template<typename T, typename Alloc>
138 struct uses_allocator_imp
140 // Use SFINAE (Substitution Failure Is Not An Error) to detect the
141 // presence of an 'allocator_type' nested type convertilble from Alloc.
144 // Match this function if TypeT::allocator_type exists and is
145 // implicitly convertible from Alloc
146 template <typename U>
147 static char test(int, typename U::allocator_type);
149 // Match this function if TypeT::allocator_type does not exist or is
150 // not convertible from Alloc.
151 template <typename U>
152 static int test(LowPriorityConversion<int>, LowPriorityConversion<Alloc>);
154 static Alloc alloc; // Declared but not defined
157 enum { value = sizeof(test<T>(0, alloc)) == sizeof(char) };
160 } //namespace container_detail {
162 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
164 //! <b>Remark</b>: Automatically detects if T has a nested allocator_type that is convertible from
165 //! Alloc. Meets the BinaryTypeTrait requirements ([meta.rqmts] 20.4.1). A program may
166 //! specialize this type to derive from true_type for a T of user-defined type if T does not
167 //! have a nested allocator_type but is nonetheless constructible using the specified Alloc.
169 //! <b>Result</b>: derived from true_type if Convertible<Alloc,T::allocator_type> and
170 //! derived from false_type otherwise.
171 template <typename T, typename Alloc>
172 struct uses_allocator
173 : boost::integral_constant<bool, container_detail::uses_allocator_imp<T, Alloc>::value>
176 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
178 namespace container_detail {
180 template <typename Alloc>
181 struct is_scoped_allocator_imp
183 template <typename T>
184 static char test(int, typename T::outer_allocator_type*);
186 template <typename T>
187 static int test(LowPriorityConversion<int>, void*);
189 static const bool value = (sizeof(char) == sizeof(test<Alloc>(0, 0)));
192 template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
193 struct outermost_allocator_type_impl
195 typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
196 typedef typename outermost_allocator_type_impl<outer_type>::type type;
199 template<class MaybeScopedAlloc>
200 struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
202 typedef MaybeScopedAlloc type;
205 template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
206 struct outermost_allocator_imp
208 typedef MaybeScopedAlloc type;
210 static type &get(MaybeScopedAlloc &a)
213 static const type &get(const MaybeScopedAlloc &a)
217 template<class MaybeScopedAlloc>
218 struct outermost_allocator_imp<MaybeScopedAlloc, true>
220 typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
221 typedef typename outermost_allocator_type_impl<outer_type>::type type;
223 static type &get(MaybeScopedAlloc &a)
224 { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
226 static const type &get(const MaybeScopedAlloc &a)
227 { return outermost_allocator_imp<outer_type>::get(a.outer_allocator()); }
230 } //namespace container_detail {
232 template <typename Alloc>
233 struct is_scoped_allocator
234 : boost::integral_constant<bool, container_detail::is_scoped_allocator_imp<Alloc>::value>
237 template <typename Alloc>
238 struct outermost_allocator
239 : container_detail::outermost_allocator_imp<Alloc>
242 template <typename Alloc>
243 typename container_detail::outermost_allocator_imp<Alloc>::type &
244 get_outermost_allocator(Alloc &a)
245 { return container_detail::outermost_allocator_imp<Alloc>::get(a); }
247 template <typename Alloc>
248 const typename container_detail::outermost_allocator_imp<Alloc>::type &
249 get_outermost_allocator(const Alloc &a)
250 { return container_detail::outermost_allocator_imp<Alloc>::get(a); }
252 namespace container_detail {
254 // Check if we can detect is_convertible using advanced SFINAE expressions
255 #if !defined(BOOST_NO_SFINAE_EXPR)
257 //! Code inspired by Mathias Gaunard's is_convertible.cpp found in the Boost mailing list
258 //! http://boost.2283326.n4.nabble.com/type-traits-is-constructible-when-decltype-is-supported-td3575452.html
261 //With variadic templates, we need a single class to implement the trait
262 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
264 template<class T, class ...Args>
265 struct is_constructible_impl
267 typedef char yes_type;
269 { char padding[2]; };
271 template<std::size_t N>
275 static yes_type test(dummy<sizeof(X(boost::move_detail::declval<Args>()...))>*);
278 static no_type test(...);
280 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
283 template<class T, class ...Args>
284 struct is_constructible
285 : boost::integral_constant<bool, is_constructible_impl<T, Args...>::value>
288 template <class T, class InnerAlloc, class ...Args>
289 struct is_constructible_with_allocator_prefix
290 : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
293 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
295 //Without variadic templates, we need to use the preprocessor to generate
296 //some specializations.
298 #define BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS \
299 BOOST_PP_ADD(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, 3)
302 //Generate N+1 template parameters so that we can specialize N
304 BOOST_PP_ENUM_TRAILING( BOOST_PP_ADD(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
305 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
308 struct is_constructible_impl;
310 //Generate N specializations, from 0 to
311 //BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS parameters
312 #define BOOST_PP_LOCAL_MACRO(n) \
313 template<class T BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)> \
314 struct is_constructible_impl \
315 <T BOOST_PP_ENUM_TRAILING_PARAMS(n, P) \
316 BOOST_PP_ENUM_TRAILING \
317 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, n) \
318 , BOOST_CONTAINER_PP_IDENTITY, void) \
321 typedef char yes_type; \
323 { char padding[2]; }; \
325 template<std::size_t N> \
329 static yes_type test(dummy<sizeof(X(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_DECLVAL, ~)))>*); \
332 static no_type test(...); \
334 static const bool value = sizeof(test<T>(0)) == sizeof(yes_type); \
338 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS)
339 #include BOOST_PP_LOCAL_ITERATE()
341 //Finally just inherit from the implementation to define he trait
343 BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS
344 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
347 struct is_constructible
348 : boost::integral_constant
350 , is_constructible_impl
352 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, P)
357 //Finally just inherit from the implementation to define he trait
360 BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2)
361 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
364 struct is_constructible_with_allocator_prefix
366 < T, allocator_arg_t, InnerAlloc
367 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2), P)
373 BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
374 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
377 struct is_constructible_with_allocator_suffix
380 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1), P)
385 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
387 #else // #if !defined(BOOST_NO_SFINAE_EXPR)
389 //Without advanced SFINAE expressions, we can't use is_constructible
390 //so backup to constructible_with_allocator_xxx
392 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
394 template < class T, class InnerAlloc, class ...Args>
395 struct is_constructible_with_allocator_prefix
396 : constructible_with_allocator_prefix<T>
399 template < class T, class InnerAlloc, class ...Args>
400 struct is_constructible_with_allocator_suffix
401 : constructible_with_allocator_suffix<T>
404 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
408 BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
409 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
412 struct is_constructible_with_allocator_prefix
413 : constructible_with_allocator_prefix<T>
418 BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
419 , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
422 struct is_constructible_with_allocator_suffix
423 : constructible_with_allocator_suffix<T>
426 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
428 #endif // #if !defined(BOOST_NO_SFINAE_EXPR)
430 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
432 template < typename OutermostAlloc
433 , typename InnerAlloc
437 inline void dispatch_allocator_prefix_suffix
438 ( boost::true_type use_alloc_prefix, OutermostAlloc& outermost_alloc
439 , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args) ...args)
441 (void)use_alloc_prefix;
442 allocator_traits<OutermostAlloc>::construct
443 ( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward<Args>(args)...);
446 template < typename OutermostAlloc
447 , typename InnerAlloc
451 inline void dispatch_allocator_prefix_suffix
452 ( boost::false_type use_alloc_prefix, OutermostAlloc& outermost_alloc
453 , InnerAlloc &inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
455 (void)use_alloc_prefix;
456 allocator_traits<OutermostAlloc>::construct
457 (outermost_alloc, p, ::boost::forward<Args>(args)..., inner_alloc);
460 template < typename OutermostAlloc
461 , typename InnerAlloc
465 inline void dispatch_uses_allocator
466 ( boost::true_type uses_allocator, OutermostAlloc& outermost_alloc
467 , InnerAlloc& inner_alloc, T* p, BOOST_FWD_REF(Args)...args)
469 (void)uses_allocator;
470 //BOOST_STATIC_ASSERT((is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>::value ||
471 // is_constructible_with_allocator_suffix<T, InnerAlloc, Args...>::value ));
472 dispatch_allocator_prefix_suffix
473 ( is_constructible_with_allocator_prefix<T, InnerAlloc, Args...>()
474 , outermost_alloc, inner_alloc, p, ::boost::forward<Args>(args)...);
477 template < typename OutermostAlloc
478 , typename InnerAlloc
482 inline void dispatch_uses_allocator
483 ( boost::false_type uses_allocator, OutermostAlloc & outermost_alloc
484 , InnerAlloc & inner_alloc
485 ,T* p, BOOST_FWD_REF(Args)...args)
487 (void)uses_allocator; (void)inner_alloc;
488 allocator_traits<OutermostAlloc>::construct
489 (outermost_alloc, p, ::boost::forward<Args>(args)...);
492 #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
494 #define BOOST_PP_LOCAL_MACRO(n) \
495 template < typename OutermostAlloc \
496 , typename InnerAlloc \
498 BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
500 inline void dispatch_allocator_prefix_suffix( \
501 boost::true_type use_alloc_prefix, \
502 OutermostAlloc& outermost_alloc, \
503 InnerAlloc& inner_alloc, \
505 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
507 (void)use_alloc_prefix, \
508 allocator_traits<OutermostAlloc>::construct \
509 (outermost_alloc, p, allocator_arg, inner_alloc \
510 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
513 template < typename OutermostAlloc \
514 , typename InnerAlloc \
516 BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
518 inline void dispatch_allocator_prefix_suffix( \
519 boost::false_type use_alloc_prefix, \
520 OutermostAlloc& outermost_alloc, \
521 InnerAlloc& inner_alloc, \
522 T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
524 (void)use_alloc_prefix; \
525 allocator_traits<OutermostAlloc>::construct \
526 (outermost_alloc, p \
527 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _) \
531 template < typename OutermostAlloc \
532 , typename InnerAlloc \
534 BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
536 inline void dispatch_uses_allocator(boost::true_type uses_allocator, \
537 OutermostAlloc& outermost_alloc, \
538 InnerAlloc& inner_alloc, \
539 T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
541 (void)uses_allocator; \
542 dispatch_allocator_prefix_suffix \
543 (is_constructible_with_allocator_prefix \
544 < T, InnerAlloc BOOST_PP_ENUM_TRAILING_PARAMS(n, P)>() \
545 , outermost_alloc, inner_alloc, p \
546 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
549 template < typename OutermostAlloc \
550 , typename InnerAlloc \
552 BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
554 inline void dispatch_uses_allocator(boost::false_type uses_allocator \
555 ,OutermostAlloc & outermost_alloc \
556 ,InnerAlloc & inner_alloc \
557 ,T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
559 (void)uses_allocator; (void)inner_alloc; \
560 allocator_traits<OutermostAlloc>::construct \
561 (outermost_alloc, p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
564 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
565 #include BOOST_PP_LOCAL_ITERATE()
567 #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
569 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
571 template <typename OuterAlloc, class ...InnerAllocs>
572 class scoped_allocator_adaptor_base
575 typedef allocator_traits<OuterAlloc> outer_traits_type;
576 BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
579 template <class OuterA2>
582 typedef scoped_allocator_adaptor_base<OuterA2, InnerAllocs...> other;
585 typedef OuterAlloc outer_allocator_type;
586 typedef scoped_allocator_adaptor<InnerAllocs...> inner_allocator_type;
587 typedef allocator_traits<inner_allocator_type> inner_traits_type;
588 typedef scoped_allocator_adaptor
589 <OuterAlloc, InnerAllocs...> scoped_allocator_type;
590 typedef boost::integral_constant<
592 outer_traits_type::propagate_on_container_copy_assignment::value ||
593 inner_allocator_type::propagate_on_container_copy_assignment::value
594 > propagate_on_container_copy_assignment;
595 typedef boost::integral_constant<
597 outer_traits_type::propagate_on_container_move_assignment::value ||
598 inner_allocator_type::propagate_on_container_move_assignment::value
599 > propagate_on_container_move_assignment;
600 typedef boost::integral_constant<
602 outer_traits_type::propagate_on_container_swap::value ||
603 inner_allocator_type::propagate_on_container_swap::value
604 > propagate_on_container_swap;
606 scoped_allocator_adaptor_base()
609 template <class OuterA2>
610 scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs &...args)
611 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
615 scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
616 : outer_allocator_type(other.outer_allocator())
617 , m_inner(other.inner_allocator())
620 scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
621 : outer_allocator_type(::boost::move(other.outer_allocator()))
622 , m_inner(::boost::move(other.inner_allocator()))
625 template <class OuterA2>
626 scoped_allocator_adaptor_base
627 (const scoped_allocator_adaptor_base<OuterA2, InnerAllocs...>& other)
628 : outer_allocator_type(other.outer_allocator())
629 , m_inner(other.inner_allocator())
632 template <class OuterA2>
633 scoped_allocator_adaptor_base
634 (BOOST_RV_REF_BEG scoped_allocator_adaptor_base
635 <OuterA2, InnerAllocs...> BOOST_RV_REF_END other)
636 : outer_allocator_type(other.outer_allocator())
637 , m_inner(other.inner_allocator())
641 struct internal_type_t{};
643 template <class OuterA2>
644 scoped_allocator_adaptor_base
646 , BOOST_FWD_REF(OuterA2) outerAlloc
647 , const inner_allocator_type &inner)
648 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
654 scoped_allocator_adaptor_base &operator=
655 (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
657 outer_allocator_type::operator=(other.outer_allocator());
658 m_inner = other.inner_allocator();
662 scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
664 outer_allocator_type::operator=(boost::move(other.outer_allocator()));
665 m_inner = ::boost::move(other.inner_allocator());
669 void swap(scoped_allocator_adaptor_base &r)
671 boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
672 boost::container::swap_dispatch(this->m_inner, r.inner_allocator());
675 friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
678 inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT
681 inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT
684 outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT
685 { return static_cast<outer_allocator_type&>(*this); }
687 const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT
688 { return static_cast<const outer_allocator_type&>(*this); }
690 scoped_allocator_type select_on_container_copy_construction() const
692 return scoped_allocator_type
694 ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
695 ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
700 inner_allocator_type m_inner;
703 #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
705 //Let's add a dummy first template parameter to allow creating
706 //specializations up to maximum InnerAlloc count
710 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
712 class scoped_allocator_adaptor_base;
714 //Specializations for the adaptor with InnerAlloc allocators
716 #define BOOST_PP_LOCAL_MACRO(n) \
717 template <typename OuterAlloc \
718 BOOST_PP_ENUM_TRAILING_PARAMS(n, class Q) \
720 class scoped_allocator_adaptor_base<OuterAlloc, true \
721 BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
722 BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
723 , BOOST_CONTAINER_PP_IDENTITY, nat) \
725 : public OuterAlloc \
727 typedef allocator_traits<OuterAlloc> outer_traits_type; \
728 BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base) \
731 template <class OuterA2> \
734 typedef scoped_allocator_adaptor_base<OuterA2, true BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
735 BOOST_PP_ENUM_TRAILING \
736 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
737 , BOOST_CONTAINER_PP_IDENTITY, nat) \
741 typedef OuterAlloc outer_allocator_type; \
742 typedef scoped_allocator_adaptor<BOOST_PP_ENUM_PARAMS(n, Q) \
743 BOOST_PP_ENUM_TRAILING \
744 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
745 , BOOST_CONTAINER_PP_IDENTITY, nat) \
746 > inner_allocator_type; \
747 typedef scoped_allocator_adaptor<OuterAlloc, BOOST_PP_ENUM_PARAMS(n, Q) \
748 BOOST_PP_ENUM_TRAILING \
749 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
750 , BOOST_CONTAINER_PP_IDENTITY, nat) \
751 > scoped_allocator_type; \
752 typedef allocator_traits<inner_allocator_type> inner_traits_type; \
753 typedef boost::integral_constant< \
755 outer_traits_type::propagate_on_container_copy_assignment::value || \
756 inner_allocator_type::propagate_on_container_copy_assignment::value \
757 > propagate_on_container_copy_assignment; \
758 typedef boost::integral_constant< \
760 outer_traits_type::propagate_on_container_move_assignment::value || \
761 inner_allocator_type::propagate_on_container_move_assignment::value \
762 > propagate_on_container_move_assignment; \
763 typedef boost::integral_constant< \
765 outer_traits_type::propagate_on_container_swap::value || \
766 inner_allocator_type::propagate_on_container_swap::value \
767 > propagate_on_container_swap; \
769 scoped_allocator_adaptor_base() \
772 template <class OuterA2> \
773 scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc \
774 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
775 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
776 , m_inner(BOOST_PP_ENUM_PARAMS(n, q)) \
779 scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other) \
780 : outer_allocator_type(other.outer_allocator()) \
781 , m_inner(other.inner_allocator()) \
784 scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
785 : outer_allocator_type(::boost::move(other.outer_allocator())) \
786 , m_inner(::boost::move(other.inner_allocator())) \
789 template <class OuterA2> \
790 scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base<OuterA2, true \
791 BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
792 BOOST_PP_ENUM_TRAILING \
793 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
794 , BOOST_CONTAINER_PP_IDENTITY, nat) \
796 : outer_allocator_type(other.outer_allocator()) \
797 , m_inner(other.inner_allocator()) \
800 template <class OuterA2> \
801 scoped_allocator_adaptor_base \
802 (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<OuterA2, true \
803 BOOST_PP_ENUM_TRAILING_PARAMS(n, Q) \
804 BOOST_PP_ENUM_TRAILING \
805 ( BOOST_PP_SUB(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, n) \
806 , BOOST_CONTAINER_PP_IDENTITY, nat) \
807 > BOOST_RV_REF_END other) \
808 : outer_allocator_type(other.outer_allocator()) \
809 , m_inner(other.inner_allocator()) \
813 struct internal_type_t{}; \
815 template <class OuterA2> \
816 scoped_allocator_adaptor_base \
818 , BOOST_FWD_REF(OuterA2) outerAlloc \
819 , const inner_allocator_type &inner) \
820 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc)) \
825 scoped_allocator_adaptor_base &operator= \
826 (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other) \
828 outer_allocator_type::operator=(other.outer_allocator()); \
829 m_inner = other.inner_allocator(); \
833 scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other) \
835 outer_allocator_type::operator=(boost::move(other.outer_allocator())); \
836 m_inner = ::boost::move(other.inner_allocator()); \
840 void swap(scoped_allocator_adaptor_base &r) \
842 boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator()); \
843 boost::container::swap_dispatch(this->m_inner, r.inner_allocator()); \
846 friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r) \
849 inner_allocator_type& inner_allocator() \
850 { return m_inner; } \
852 inner_allocator_type const& inner_allocator() const \
853 { return m_inner; } \
855 outer_allocator_type & outer_allocator() \
856 { return static_cast<outer_allocator_type&>(*this); } \
858 const outer_allocator_type &outer_allocator() const \
859 { return static_cast<const outer_allocator_type&>(*this); } \
861 scoped_allocator_type select_on_container_copy_construction() const \
863 return scoped_allocator_type \
865 ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator()) \
866 ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator()) \
870 inner_allocator_type m_inner; \
873 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
874 #include BOOST_PP_LOCAL_ITERATE()
876 #endif //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
878 //Specialization for adaptor without any InnerAlloc
879 template <typename OuterAlloc>
880 class scoped_allocator_adaptor_base
882 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
884 BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat)
889 BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
895 typedef scoped_allocator_adaptor_base
896 <typename allocator_traits<OuterAlloc>::template portable_rebind_alloc<U>::type
897 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
899 BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
904 typedef OuterAlloc outer_allocator_type;
905 typedef allocator_traits<OuterAlloc> outer_traits_type;
906 typedef scoped_allocator_adaptor<OuterAlloc> inner_allocator_type;
907 typedef inner_allocator_type scoped_allocator_type;
908 typedef allocator_traits<inner_allocator_type> inner_traits_type;
909 typedef typename outer_traits_type::
910 propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
911 typedef typename outer_traits_type::
912 propagate_on_container_move_assignment propagate_on_container_move_assignment;
913 typedef typename outer_traits_type::
914 propagate_on_container_swap propagate_on_container_swap;
916 scoped_allocator_adaptor_base()
919 template <class OuterA2>
920 scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
921 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
924 scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
925 : outer_allocator_type(other.outer_allocator())
928 scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
929 : outer_allocator_type(::boost::move(other.outer_allocator()))
932 template <class OuterA2>
933 scoped_allocator_adaptor_base
934 (const scoped_allocator_adaptor_base<
936 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
938 BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
941 : outer_allocator_type(other.outer_allocator())
944 template <class OuterA2>
945 scoped_allocator_adaptor_base
946 (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<
948 #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
950 BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
952 > BOOST_RV_REF_END other)
953 : outer_allocator_type(other.outer_allocator())
957 struct internal_type_t{};
959 template <class OuterA2>
960 scoped_allocator_adaptor_base(internal_type_t, BOOST_FWD_REF(OuterA2) outerAlloc, const inner_allocator_type &)
961 : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
965 scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
967 outer_allocator_type::operator=(other.outer_allocator());
971 scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
973 outer_allocator_type::operator=(boost::move(other.outer_allocator()));
977 void swap(scoped_allocator_adaptor_base &r)
979 boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
982 friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
985 inner_allocator_type& inner_allocator()
986 { return static_cast<inner_allocator_type&>(*this); }
988 inner_allocator_type const& inner_allocator() const
989 { return static_cast<const inner_allocator_type&>(*this); }
991 outer_allocator_type & outer_allocator()
992 { return static_cast<outer_allocator_type&>(*this); }
994 const outer_allocator_type &outer_allocator() const
995 { return static_cast<const outer_allocator_type&>(*this); }
997 scoped_allocator_type select_on_container_copy_construction() const
999 return scoped_allocator_type
1001 ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
1002 //Don't use inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
1003 //as inner_allocator() is equal to *this and that would trigger an infinite loop
1004 , this->inner_allocator()
1009 } //namespace container_detail {
1011 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1014 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1016 #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1018 //! This class is a C++03-compatible implementation of std::scoped_allocator_adaptor.
1019 //! The class template scoped_allocator_adaptor is an allocator template that specifies
1020 //! the memory resource (the outer allocator) to be used by a container (as any other
1021 //! allocator does) and also specifies an inner allocator resource to be passed to
1022 //! the constructor of every element within the container.
1025 //! instantiated with one outer and zero or more inner allocator types. If
1026 //! instantiated with only one allocator type, the inner allocator becomes the
1027 //! scoped_allocator_adaptor itself, thus using the same allocator resource for the
1028 //! container and every element within the container and, if the elements themselves
1029 //! are containers, each of their elements recursively. If instantiated with more than
1030 //! one allocator, the first allocator is the outer allocator for use by the container,
1031 //! the second allocator is passed to the constructors of the container's elements,
1032 //! and, if the elements themselves are containers, the third allocator is passed to
1033 //! the elements' elements, and so on. If containers are nested to a depth greater
1034 //! than the number of allocators, the last allocator is used repeatedly, as in the
1035 //! single-allocator case, for any remaining recursions.
1037 //! [<b>Note</b>: The
1038 //! scoped_allocator_adaptor is derived from the outer allocator type so it can be
1039 //! substituted for the outer allocator type in most expressions. -end note]
1041 //! In the construct member functions, <code>OUTERMOST(x)</code> is x if x does not have
1042 //! an <code>outer_allocator()</code> member function and
1043 //! <code>OUTERMOST(x.outer_allocator())</code> otherwise; <code>OUTERMOST_ALLOC_TRAITS(x)</code> is
1044 //! <code>allocator_traits<decltype(OUTERMOST(x))></code>.
1046 //! [<b>Note</b>: <code>OUTERMOST(x)</code> and
1047 //! <code>OUTERMOST_ALLOC_TRAITS(x)</code> are recursive operations. It is incumbent upon
1048 //! the definition of <code>outer_allocator()</code> to ensure that the recursion terminates.
1049 //! It will terminate for all instantiations of scoped_allocator_adaptor. -end note]
1050 template <typename OuterAlloc, typename ...InnerAllocs>
1051 class scoped_allocator_adaptor
1053 #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1055 template <typename OuterAlloc, typename ...InnerAllocs>
1056 class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
1058 #endif // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1060 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1062 template <typename OuterAlloc
1063 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1065 class scoped_allocator_adaptor
1067 : public container_detail::scoped_allocator_adaptor_base
1069 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1072 , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1076 BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
1079 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1080 typedef container_detail::scoped_allocator_adaptor_base
1082 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1085 , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1088 typedef typename base_type::internal_type_t internal_type_t;
1089 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1090 typedef OuterAlloc outer_allocator_type;
1091 //! Type: For exposition only
1093 typedef allocator_traits<OuterAlloc> outer_traits_type;
1094 //! Type: <code>scoped_allocator_adaptor<OuterAlloc></code> if <code>sizeof...(InnerAllocs)</code> is zero; otherwise,
1095 //! <code>scoped_allocator_adaptor<InnerAllocs...></code>.
1096 typedef typename base_type::inner_allocator_type inner_allocator_type;
1097 typedef allocator_traits<inner_allocator_type> inner_traits_type;
1098 typedef typename outer_traits_type::value_type value_type;
1099 typedef typename outer_traits_type::size_type size_type;
1100 typedef typename outer_traits_type::difference_type difference_type;
1101 typedef typename outer_traits_type::pointer pointer;
1102 typedef typename outer_traits_type::const_pointer const_pointer;
1103 typedef typename outer_traits_type::void_pointer void_pointer;
1104 typedef typename outer_traits_type::const_void_pointer const_void_pointer;
1105 //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_copy_assignment::value</code> is
1106 //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
1107 typedef typename base_type::
1108 propagate_on_container_copy_assignment propagate_on_container_copy_assignment;
1109 //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_move_assignment::value</code> is
1110 //! true for any <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
1111 typedef typename base_type::
1112 propagate_on_container_move_assignment propagate_on_container_move_assignment;
1113 //! Type: <code>true_type</code> if <code>allocator_traits<Allocator>::propagate_on_container_swap::value</code> is true for any
1114 //! <code>Allocator</code> in the set of <code>OuterAlloc</code> and <code>InnerAllocs...</code>; otherwise, false_type.
1115 typedef typename base_type::
1116 propagate_on_container_swap propagate_on_container_swap;
1118 //! Type: Rebinds scoped allocator to
1119 //! <code>typedef scoped_allocator_adaptor
1120 //! < typename outer_traits_type::template portable_rebind_alloc<U>::type
1121 //! , InnerAllocs... ></code>
1125 typedef scoped_allocator_adaptor
1126 < typename outer_traits_type::template portable_rebind_alloc<U>::type
1127 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1130 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1135 //! <b>Effects</b>: value-initializes the OuterAlloc base class
1136 //! and the inner allocator object.
1137 scoped_allocator_adaptor()
1140 ~scoped_allocator_adaptor()
1143 //! <b>Effects</b>: initializes each allocator within the adaptor with
1144 //! the corresponding allocator from other.
1145 scoped_allocator_adaptor(const scoped_allocator_adaptor& other)
1146 : base_type(other.base())
1149 //! <b>Effects</b>: move constructs each allocator within the adaptor with
1150 //! the corresponding allocator from other.
1151 scoped_allocator_adaptor(BOOST_RV_REF(scoped_allocator_adaptor) other)
1152 : base_type(::boost::move(other.base()))
1155 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1157 //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1159 //! <b>Effects</b>: initializes the OuterAlloc base class with boost::forward<OuterA2>(outerAlloc) and inner
1160 //! with innerAllocs...(hence recursively initializing each allocator within the adaptor with the
1161 //! corresponding allocator from the argument list).
1162 template <class OuterA2>
1163 scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc, const InnerAllocs & ...innerAllocs)
1164 : base_type(::boost::forward<OuterA2>(outerAlloc), innerAllocs...)
1166 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1168 #define BOOST_PP_LOCAL_MACRO(n) \
1169 template <class OuterA2> \
1170 scoped_allocator_adaptor(BOOST_FWD_REF(OuterA2) outerAlloc \
1171 BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_CONST_REF_PARAM_LIST_Q, _)) \
1172 : base_type(::boost::forward<OuterA2>(outerAlloc) \
1173 BOOST_PP_ENUM_TRAILING_PARAMS(n, q) \
1177 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1178 #include BOOST_PP_LOCAL_ITERATE()
1180 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1182 //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1184 //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator from other.
1185 template <class OuterA2>
1186 scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2
1187 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1190 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1193 : base_type(other.base())
1196 //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1198 //! <b>Effects</b>: initializes each allocator within the adaptor with the corresponding allocator
1199 //! rvalue from other.
1200 template <class OuterA2>
1201 scoped_allocator_adaptor(BOOST_RV_REF_BEG scoped_allocator_adaptor<OuterA2
1202 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1205 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1207 > BOOST_RV_REF_END other)
1208 : base_type(::boost::move(other.base()))
1211 scoped_allocator_adaptor &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor) other)
1212 { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(static_cast<const base_type &>(other))); }
1214 scoped_allocator_adaptor &operator=(BOOST_RV_REF(scoped_allocator_adaptor) other)
1215 { return static_cast<scoped_allocator_adaptor&>(base_type::operator=(boost::move(static_cast<base_type&>(other)))); }
1217 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
1218 //! <b>Effects</b>: swaps *this with r.
1220 void swap(scoped_allocator_adaptor &r);
1222 //! <b>Effects</b>: swaps *this with r.
1224 friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
1227 //! <code>static_cast<OuterAlloc&>(*this)</code>.
1228 outer_allocator_type & outer_allocator() BOOST_CONTAINER_NOEXCEPT;
1231 //! <code>static_cast<const OuterAlloc&>(*this)</code>.
1232 const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT;
1235 //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
1236 inner_allocator_type& inner_allocator() BOOST_CONTAINER_NOEXCEPT;
1239 //! *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
1240 inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT;
1242 #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
1245 //! <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>.
1246 size_type max_size() const BOOST_CONTAINER_NOEXCEPT
1248 return outer_traits_type::max_size(this->outer_allocator());
1252 //! calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>.
1254 void destroy(T* p) BOOST_CONTAINER_NOEXCEPT
1256 allocator_traits<typename outermost_allocator<OuterAlloc>::type>
1257 ::destroy(get_outermost_allocator(this->outer_allocator()), p);
1261 //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
1262 pointer allocate(size_type n)
1264 return outer_traits_type::allocate(this->outer_allocator(), n);
1268 //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
1269 pointer allocate(size_type n, const_void_pointer hint)
1271 return outer_traits_type::allocate(this->outer_allocator(), n, hint);
1275 //! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>.
1276 void deallocate(pointer p, size_type n)
1278 outer_traits_type::deallocate(this->outer_allocator(), p, n);
1281 #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
1282 //! <b>Returns</b>: Allocator new scoped_allocator_adaptor object where each allocator
1283 //! A in the adaptor is initialized from the result of calling
1284 //! <code>allocator_traits<Allocator>::select_on_container_copy_construction()</code> on
1285 //! the corresponding allocator in *this.
1286 scoped_allocator_adaptor select_on_container_copy_construction() const;
1287 #endif //BOOST_CONTAINER_DOXYGEN_INVOKED
1289 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1290 base_type &base() { return *this; }
1292 const base_type &base() const { return *this; }
1293 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1295 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1298 //! 1) If <code>uses_allocator<T, inner_allocator_type>::value</code> is false calls
1299 //! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct
1300 //! (OUTERMOST(*this), p, std::forward<Args>(args)...)</code>.
1302 //! 2) Otherwise, if <code>uses_allocator<T, inner_allocator_type>::value</code> is true and
1303 //! <code>is_constructible<T, allocator_arg_t, inner_allocator_type, Args...>::value</code> is true, calls
1304 //! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p, allocator_arg,
1305 //! inner_allocator(), std::forward<Args>(args)...)</code>.
1307 //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't
1308 //! be implemented so that condition will be replaced by
1309 //! constructible_with_allocator_prefix<T>::value. -end note]
1311 //! 3) Otherwise, if uses_allocator<T, inner_allocator_type>::value is true and
1312 //! <code>is_constructible<T, Args..., inner_allocator_type>::value</code> is true, calls
1313 //! <code>OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST(*this), p,
1314 //! std::forward<Args>(args)..., inner_allocator())</code>.
1316 //! [<b>Note</b>: In compilers without advanced decltype SFINAE support, <code>is_constructible</code> can't be
1317 //! implemented so that condition will be replaced by
1318 //! <code>constructible_with_allocator_suffix<T>::value</code>. -end note]
1320 //! 4) Otherwise, the program is ill-formed.
1322 //! [<b>Note</b>: An error will result if <code>uses_allocator</code> evaluates
1323 //! to true but the specific constructor does not take an allocator. This definition prevents a silent
1324 //! failure to pass an inner allocator to a contained element. -end note]
1325 template < typename T, class ...Args>
1326 #if defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1329 typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type
1331 construct(T* p, BOOST_FWD_REF(Args)...args)
1333 container_detail::dispatch_uses_allocator
1334 ( uses_allocator<T, inner_allocator_type>()
1335 , get_outermost_allocator(this->outer_allocator())
1336 , this->inner_allocator()
1337 , p, ::boost::forward<Args>(args)...);
1340 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1342 //Disable this overload if the first argument is pair as some compilers have
1343 //overload selection problems when the first parameter is a pair.
1344 #define BOOST_PP_LOCAL_MACRO(n) \
1345 template < typename T \
1346 BOOST_PP_ENUM_TRAILING_PARAMS(n, class P) \
1348 typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type \
1349 construct(T* p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _)) \
1351 container_detail::dispatch_uses_allocator \
1352 ( uses_allocator<T, inner_allocator_type>() \
1353 , get_outermost_allocator(this->outer_allocator()) \
1354 , this->inner_allocator() \
1355 , p BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_FORWARD, _)); \
1358 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1359 #include BOOST_PP_LOCAL_ITERATE()
1361 #endif // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1363 template <class T1, class T2>
1364 void construct(std::pair<T1,T2>* p)
1365 { this->construct_pair(p); }
1367 template <class T1, class T2>
1368 void construct(container_detail::pair<T1,T2>* p)
1369 { this->construct_pair(p); }
1371 template <class T1, class T2, class U, class V>
1372 void construct(std::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
1373 { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
1375 template <class T1, class T2, class U, class V>
1376 void construct(container_detail::pair<T1, T2>* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
1377 { this->construct_pair(p, ::boost::forward<U>(x), ::boost::forward<V>(y)); }
1379 template <class T1, class T2, class U, class V>
1380 void construct(std::pair<T1, T2>* p, const std::pair<U, V>& x)
1381 { this->construct_pair(p, x); }
1383 template <class T1, class T2, class U, class V>
1384 void construct( container_detail::pair<T1, T2>* p
1385 , const container_detail::pair<U, V>& x)
1386 { this->construct_pair(p, x); }
1388 template <class T1, class T2, class U, class V>
1389 void construct( std::pair<T1, T2>* p
1390 , BOOST_RV_REF_BEG std::pair<U, V> BOOST_RV_REF_END x)
1391 { this->construct_pair(p, x); }
1393 template <class T1, class T2, class U, class V>
1394 void construct( container_detail::pair<T1, T2>* p
1395 , BOOST_RV_REF_BEG container_detail::pair<U, V> BOOST_RV_REF_END x)
1396 { this->construct_pair(p, x); }
1398 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1400 template <class Pair>
1401 void construct_pair(Pair* p)
1403 this->construct(container_detail::addressof(p->first));
1405 this->construct(container_detail::addressof(p->second));
1408 this->destroy(container_detail::addressof(p->first));
1414 template <class Pair, class U, class V>
1415 void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
1417 this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
1419 this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
1422 this->destroy(container_detail::addressof(p->first));
1428 template <class Pair, class Pair2>
1429 void construct_pair(Pair* p, const Pair2& pr)
1431 this->construct(container_detail::addressof(p->first), pr.first);
1433 this->construct(container_detail::addressof(p->second), pr.second);
1436 this->destroy(container_detail::addressof(p->first));
1442 template <class Pair, class Pair2>
1443 void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
1445 this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
1447 this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
1450 this->destroy(container_detail::addressof(p->first));
1456 //template <class T1, class T2, class... Args1, class... Args2>
1457 //void construct(pair<T1, T2>* p, piecewise_construct_t, tuple<Args1...> x, tuple<Args2...> y);
1461 template <class OuterA2>
1462 scoped_allocator_adaptor(internal_type_t, BOOST_FWD_REF(OuterA2) outer, const inner_allocator_type& inner)
1463 : base_type(internal_type_t(), ::boost::forward<OuterA2>(outer), inner)
1466 #endif //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1469 template <typename OuterA1, typename OuterA2
1470 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1471 , typename... InnerAllocs
1473 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1476 inline bool operator==(
1477 const scoped_allocator_adaptor<OuterA1
1478 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1481 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1484 const scoped_allocator_adaptor<OuterA2
1485 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1488 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1492 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1493 const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
1495 const bool has_zero_inner =
1496 boost::container::container_detail::is_same
1497 <Q0, container_detail::nat>::value;
1500 return a.outer_allocator() == b.outer_allocator()
1501 && (has_zero_inner || a.inner_allocator() == b.inner_allocator());
1504 template <typename OuterA1, typename OuterA2
1505 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1506 , typename... InnerAllocs
1508 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1511 inline bool operator!=(
1512 const scoped_allocator_adaptor<OuterA1
1513 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1516 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1519 const scoped_allocator_adaptor<OuterA2
1520 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1523 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1530 }} // namespace boost { namespace container {
1532 #include <boost/container/detail/config_end.hpp>
1534 #endif // BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP