Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / container / scoped_allocator.hpp
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 #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>
31 #include <utility>
32 #include <boost/container/detail/pair.hpp>
33 #include <boost/move/utility_core.hpp>
34 #include <boost/core/no_exceptions_support.hpp>
35
36 namespace boost { namespace container {
37
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
41 //! allocator_type.
42 //!
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
47 //! ill-formed.
48 //!
49 //! <code>
50 //!  template <class T, class Allocator = allocator<T> >
51 //!  class Z {
52 //!    public:
53 //!      typedef Allocator allocator_type;
54 //!
55 //!    // Default constructor with optional allocator suffix
56 //!    Z(const allocator_type& a = allocator_type());
57 //!
58 //!    // Copy constructor and allocator-extended copy constructor
59 //!    Z(const Z& zz);
60 //!    Z(const Z& zz, const allocator_type& a);
61 //! };
62 //!
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 { };
67 //! </code>
68 //!
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.
73 //!
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.
77 template <class T>
78 struct constructible_with_allocator_suffix
79    : ::boost::false_type
80 {};
81
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.
86 //!
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.
92 //!
93 //! <code>
94 //! template <class T, class Allocator = allocator<T> >
95 //! class Y {
96 //!    public:
97 //!       typedef Allocator allocator_type;
98 //!
99 //!       // Default constructor with and allocator-extended default constructor
100 //!       Y();
101 //!       Y(allocator_arg_t, const allocator_type& a);
102 //!
103 //!       // Copy constructor and allocator-extended copy constructor
104 //!       Y(const Y& yy);
105 //!       Y(allocator_arg_t, const allocator_type& a, const Y& yy);
106 //!
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);
111 //! };
112 //!
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 { };
117 //!
118 //! </code>
119 //!
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.
124 //!
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.
128 template <class T>
129 struct constructible_with_allocator_prefix
130     : ::boost::false_type
131 {};
132
133 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
134
135 namespace container_detail {
136
137 template<typename T, typename Alloc>
138 struct uses_allocator_imp
139 {
140    // Use SFINAE (Substitution Failure Is Not An Error) to detect the
141    // presence of an 'allocator_type' nested type convertilble from Alloc.
142
143    private:
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);
148
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>);
153
154    static Alloc alloc;  // Declared but not defined
155
156    public:
157    enum { value = sizeof(test<T>(0, alloc)) == sizeof(char) };
158 };
159
160 }  //namespace container_detail {
161
162 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
163
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.
168 //!
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>
174 {};
175
176 #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
177
178 namespace container_detail {
179
180 template <typename Alloc>
181 struct is_scoped_allocator_imp
182 {
183    template <typename T>
184    static char test(int, typename T::outer_allocator_type*);
185
186    template <typename T>
187    static int test(LowPriorityConversion<int>, void*);
188
189    static const bool value = (sizeof(char) == sizeof(test<Alloc>(0, 0)));
190 };
191
192 template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
193 struct outermost_allocator_type_impl
194 {
195    typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
196    typedef typename outermost_allocator_type_impl<outer_type>::type type;
197 };
198
199 template<class MaybeScopedAlloc>
200 struct outermost_allocator_type_impl<MaybeScopedAlloc, false>
201 {
202    typedef MaybeScopedAlloc type;
203 };
204
205 template<class MaybeScopedAlloc, bool = is_scoped_allocator_imp<MaybeScopedAlloc>::value >
206 struct outermost_allocator_imp
207 {
208    typedef MaybeScopedAlloc type;
209
210    static type &get(MaybeScopedAlloc &a)
211    {  return a;  }
212
213    static const type &get(const MaybeScopedAlloc &a)
214    {  return a;  }
215 };
216
217 template<class MaybeScopedAlloc>
218 struct outermost_allocator_imp<MaybeScopedAlloc, true>
219 {
220    typedef typename MaybeScopedAlloc::outer_allocator_type outer_type;
221    typedef typename outermost_allocator_type_impl<outer_type>::type type;
222
223    static type &get(MaybeScopedAlloc &a)
224    {  return outermost_allocator_imp<outer_type>::get(a.outer_allocator());  }
225
226    static const type &get(const MaybeScopedAlloc &a)
227    {  return outermost_allocator_imp<outer_type>::get(a.outer_allocator());  }
228 };
229
230 }  //namespace container_detail {
231
232 template <typename Alloc>
233 struct is_scoped_allocator
234    : boost::integral_constant<bool, container_detail::is_scoped_allocator_imp<Alloc>::value>
235 {};
236
237 template <typename Alloc>
238 struct outermost_allocator
239    : container_detail::outermost_allocator_imp<Alloc>
240 {};
241
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);   }
246
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);   }
251
252 namespace container_detail {
253
254 // Check if we can detect is_convertible using advanced SFINAE expressions
255 #if !defined(BOOST_NO_SFINAE_EXPR)
256
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
259    //! Thanks Mathias!
260
261    //With variadic templates, we need a single class to implement the trait
262    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
263
264    template<class T, class ...Args>
265    struct is_constructible_impl
266    {
267       typedef char yes_type;
268       struct no_type
269       { char padding[2]; };
270
271       template<std::size_t N>
272       struct dummy;
273
274       template<class X>
275       static yes_type test(dummy<sizeof(X(boost::move_detail::declval<Args>()...))>*);
276
277       template<class X>
278       static no_type test(...);
279
280       static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);
281    };
282
283    template<class T, class ...Args>
284    struct is_constructible
285       : boost::integral_constant<bool, is_constructible_impl<T, Args...>::value>
286    {};
287
288    template <class T, class InnerAlloc, class ...Args>
289    struct is_constructible_with_allocator_prefix
290       : is_constructible<T, allocator_arg_t, InnerAlloc, Args...>
291    {};
292
293    #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
294
295    //Without variadic templates, we need to use the preprocessor to generate
296    //some specializations.
297
298    #define BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS \
299       BOOST_PP_ADD(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, 3)
300    //!
301
302    //Generate N+1 template parameters so that we can specialize N
303    template<class T
304             BOOST_PP_ENUM_TRAILING( BOOST_PP_ADD(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
305                                  , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
306                                  , void)
307          >
308    struct is_constructible_impl;
309
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)                                                   \
319       , void>                                                                                      \
320    {                                                                                               \
321       typedef char yes_type;                                                                       \
322       struct no_type                                                                               \
323       { char padding[2]; };                                                                        \
324                                                                                                    \
325       template<std::size_t N>                                                                      \
326       struct dummy;                                                                                \
327                                                                                                    \
328       template<class X>                                                                            \
329       static yes_type test(dummy<sizeof(X(BOOST_PP_ENUM(n, BOOST_CONTAINER_PP_DECLVAL, ~)))>*);    \
330                                                                                                    \
331       template<class X>                                                                            \
332       static no_type test(...);                                                                    \
333                                                                                                    \
334       static const bool value = sizeof(test<T>(0)) == sizeof(yes_type);                            \
335    };                                                                                              \
336    //!
337
338    #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS)
339    #include BOOST_PP_LOCAL_ITERATE()
340
341    //Finally just inherit from the implementation to define he trait
342    template< class T
343            BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS
344                                  , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
345                                  , void)
346            >
347    struct is_constructible
348       : boost::integral_constant
349          < bool
350          , is_constructible_impl
351             < T
352             BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, P)
353             , void>::value
354          >
355    {};
356
357    //Finally just inherit from the implementation to define he trait
358    template <class T
359             ,class InnerAlloc
360             BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2)
361                                  , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
362                                  , void)
363             >
364    struct is_constructible_with_allocator_prefix
365       : is_constructible
366          < T, allocator_arg_t, InnerAlloc
367          BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 2), P)
368          >
369    {};
370 /*
371    template <class T
372             ,class InnerAlloc
373             BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1)
374                                  , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
375                                  , void)
376             >
377    struct is_constructible_with_allocator_suffix
378       : is_constructible
379          < T
380          BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_SUB(BOOST_CONTAINER_MAX_IS_CONSTRUCTIBLE_PARAMETERS, 1), P)
381          , InnerAlloc
382          >
383    {};*/
384
385    #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
386
387 #else    // #if !defined(BOOST_NO_SFINAE_EXPR)
388
389    //Without advanced SFINAE expressions, we can't use is_constructible
390    //so backup to constructible_with_allocator_xxx
391
392    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
393
394    template < class T, class InnerAlloc, class ...Args>
395    struct is_constructible_with_allocator_prefix
396       : constructible_with_allocator_prefix<T>
397    {};
398 /*
399    template < class T, class InnerAlloc, class ...Args>
400    struct is_constructible_with_allocator_suffix
401       : constructible_with_allocator_suffix<T>
402    {};*/
403
404    #else    // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
405
406    template < class T
407             , class InnerAlloc
408             BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
409                                   , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
410                                   , void)
411             >
412    struct is_constructible_with_allocator_prefix
413       : constructible_with_allocator_prefix<T>
414    {};
415 /*
416    template < class T
417             , class InnerAlloc
418             BOOST_PP_ENUM_TRAILING( BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS
419                                   , BOOST_CONTAINER_PP_TEMPLATE_PARAM_WITH_DEFAULT
420                                   , void)
421             >
422    struct is_constructible_with_allocator_suffix
423       : constructible_with_allocator_suffix<T>
424    {};*/
425
426    #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
427
428 #endif   // #if !defined(BOOST_NO_SFINAE_EXPR)
429
430 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
431
432 template < typename OutermostAlloc
433          , typename InnerAlloc
434          , typename T
435          , class ...Args
436          >
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)
440 {
441    (void)use_alloc_prefix;
442    allocator_traits<OutermostAlloc>::construct
443       ( outermost_alloc, p, allocator_arg, inner_alloc, ::boost::forward<Args>(args)...);
444 }
445
446 template < typename OutermostAlloc
447          , typename InnerAlloc
448          , typename T
449          , class ...Args
450          >
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)
454 {
455    (void)use_alloc_prefix;
456    allocator_traits<OutermostAlloc>::construct
457       (outermost_alloc, p, ::boost::forward<Args>(args)..., inner_alloc);
458 }
459
460 template < typename OutermostAlloc
461          , typename InnerAlloc
462          , typename T
463          , class ...Args
464          >
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)
468 {
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)...);
475 }
476
477 template < typename OutermostAlloc
478          , typename InnerAlloc
479          , typename T
480          , class ...Args
481          >
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)
486 {
487    (void)uses_allocator; (void)inner_alloc;
488    allocator_traits<OutermostAlloc>::construct
489       (outermost_alloc, p, ::boost::forward<Args>(args)...);
490 }
491
492 #else    //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
493
494 #define BOOST_PP_LOCAL_MACRO(n)                                                              \
495 template < typename OutermostAlloc                                                           \
496          , typename InnerAlloc                                                               \
497          , typename T                                                                        \
498          BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)                                           \
499          >                                                                                   \
500 inline void dispatch_allocator_prefix_suffix(                                                \
501                                        boost::true_type  use_alloc_prefix,                   \
502                                        OutermostAlloc& outermost_alloc,                      \
503                                        InnerAlloc&    inner_alloc,                           \
504                                        T* p                                                  \
505                               BOOST_PP_ENUM_TRAILING(n, BOOST_CONTAINER_PP_PARAM_LIST, _))   \
506 {                                                                                            \
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, _));                      \
511 }                                                                                            \
512                                                                                              \
513 template < typename OutermostAlloc                                                           \
514          , typename InnerAlloc                                                               \
515          , typename T                                                                        \
516          BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)                                           \
517          >                                                                                   \
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, _)) \
523 {                                                                                            \
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, _)                        \
528       , inner_alloc);                                                                        \
529 }                                                                                            \
530                                                                                              \
531 template < typename OutermostAlloc                                                           \
532          , typename InnerAlloc                                                               \
533          , typename T                                                                        \
534          BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)                                           \
535          >                                                                                   \
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, _))    \
540 {                                                                                            \
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, _));                    \
547 }                                                                                            \
548                                                                                              \
549 template < typename OutermostAlloc                                                           \
550          , typename InnerAlloc                                                               \
551          , typename T                                                                        \
552          BOOST_PP_ENUM_TRAILING_PARAMS(n, class P)                                           \
553          >                                                                                   \
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, _))   \
558 {                                                                                            \
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, _));   \
562 }                                                                                            \
563 //!
564 #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
565 #include BOOST_PP_LOCAL_ITERATE()
566
567 #endif   //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
568
569 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
570
571 template <typename OuterAlloc, class ...InnerAllocs>
572 class scoped_allocator_adaptor_base
573    : public OuterAlloc
574 {
575    typedef allocator_traits<OuterAlloc> outer_traits_type;
576    BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
577
578    public:
579    template <class OuterA2>
580    struct rebind_base
581    {
582       typedef scoped_allocator_adaptor_base<OuterA2, InnerAllocs...> other;
583    };
584
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<
591       bool,
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<
596       bool,
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<
601       bool,
602       outer_traits_type::propagate_on_container_swap::value ||
603       inner_allocator_type::propagate_on_container_swap::value
604       > propagate_on_container_swap;
605
606    scoped_allocator_adaptor_base()
607       {}
608
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))
612       , m_inner(args...)
613       {}
614
615    scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
616       : outer_allocator_type(other.outer_allocator())
617       , m_inner(other.inner_allocator())
618       {}
619
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()))
623       {}
624
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())
630       {}
631
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())
638       {}
639
640    public:
641    struct internal_type_t{};
642
643    template <class OuterA2>
644    scoped_allocator_adaptor_base
645       ( internal_type_t
646       , BOOST_FWD_REF(OuterA2) outerAlloc
647       , const inner_allocator_type &inner)
648       : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
649       , m_inner(inner)
650    {}
651
652    public:
653
654    scoped_allocator_adaptor_base &operator=
655       (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
656    {
657       outer_allocator_type::operator=(other.outer_allocator());
658       m_inner = other.inner_allocator();
659       return *this;
660    }
661
662    scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
663    {
664       outer_allocator_type::operator=(boost::move(other.outer_allocator()));
665       m_inner = ::boost::move(other.inner_allocator());
666       return *this;
667    }
668
669    void swap(scoped_allocator_adaptor_base &r)
670    {
671       boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
672       boost::container::swap_dispatch(this->m_inner, r.inner_allocator());
673    }
674
675    friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
676    {  l.swap(r);  }
677
678    inner_allocator_type&       inner_allocator() BOOST_CONTAINER_NOEXCEPT
679       { return m_inner; }
680
681    inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT
682       { return m_inner; }
683
684    outer_allocator_type      & outer_allocator() BOOST_CONTAINER_NOEXCEPT
685       { return static_cast<outer_allocator_type&>(*this); }
686
687    const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT
688       { return static_cast<const outer_allocator_type&>(*this); }
689
690    scoped_allocator_type select_on_container_copy_construction() const
691    {
692       return scoped_allocator_type
693          (internal_type_t()
694          ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())
695          ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())
696          );
697    }
698
699    private:
700    inner_allocator_type m_inner;
701 };
702
703 #else //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
704
705 //Let's add a dummy first template parameter to allow creating
706 //specializations up to maximum InnerAlloc count
707 template <
708    typename OuterAlloc
709    , bool Dummy
710    BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
711    >
712 class scoped_allocator_adaptor_base;
713
714 //Specializations for the adaptor with InnerAlloc allocators
715
716 #define BOOST_PP_LOCAL_MACRO(n)                                                                 \
717 template <typename OuterAlloc                                                                   \
718 BOOST_PP_ENUM_TRAILING_PARAMS(n, class Q)                                                       \
719 >                                                                                               \
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)                                    \
724    >                                                                                            \
725    : public OuterAlloc                                                                          \
726 {                                                                                               \
727    typedef allocator_traits<OuterAlloc> outer_traits_type;                                      \
728    BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)                                    \
729                                                                                                 \
730    public:                                                                                      \
731    template <class OuterA2>                                                                     \
732    struct rebind_base                                                                           \
733    {                                                                                            \
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)                                                 \
738          > other;                                                                               \
739    };                                                                                           \
740                                                                                                 \
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<                                                            \
754       bool,                                                                                     \
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<                                                            \
759       bool,                                                                                     \
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<                                                            \
764       bool,                                                                                     \
765       outer_traits_type::propagate_on_container_swap::value ||                                  \
766       inner_allocator_type::propagate_on_container_swap::value                                  \
767       > propagate_on_container_swap;                                                            \
768                                                                                                 \
769    scoped_allocator_adaptor_base()                                                              \
770       {}                                                                                        \
771                                                                                                 \
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))                                                     \
777       {}                                                                                        \
778                                                                                                 \
779    scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)                    \
780       : outer_allocator_type(other.outer_allocator())                                           \
781       , m_inner(other.inner_allocator())                                                        \
782       {}                                                                                        \
783                                                                                                 \
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()))                                         \
787       {}                                                                                        \
788                                                                                                 \
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)                                                 \
795          >& other)                                                                              \
796       : outer_allocator_type(other.outer_allocator())                                           \
797       , m_inner(other.inner_allocator())                                                        \
798       {}                                                                                        \
799                                                                                                 \
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())                                                        \
810       {}                                                                                        \
811                                                                                                 \
812    public:                                                                                      \
813    struct internal_type_t{};                                                                    \
814                                                                                                 \
815    template <class OuterA2>                                                                     \
816    scoped_allocator_adaptor_base                                                                \
817       ( internal_type_t                                                                         \
818       , BOOST_FWD_REF(OuterA2) outerAlloc                                                       \
819       , const inner_allocator_type &inner)                                                      \
820       : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))                             \
821       , m_inner(inner)                                                                          \
822    {}                                                                                           \
823                                                                                                 \
824    public:                                                                                      \
825    scoped_allocator_adaptor_base &operator=                                                     \
826       (BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)                              \
827    {                                                                                            \
828       outer_allocator_type::operator=(other.outer_allocator());                                 \
829       m_inner = other.inner_allocator();                                                        \
830       return *this;                                                                             \
831    }                                                                                            \
832                                                                                                 \
833    scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)  \
834    {                                                                                            \
835       outer_allocator_type::operator=(boost::move(other.outer_allocator()));                    \
836       m_inner = ::boost::move(other.inner_allocator());                                         \
837       return *this;                                                                             \
838    }                                                                                            \
839                                                                                                 \
840    void swap(scoped_allocator_adaptor_base &r)                                                  \
841    {                                                                                            \
842       boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());            \
843       boost::container::swap_dispatch(this->m_inner, r.inner_allocator());                      \
844    }                                                                                            \
845                                                                                                 \
846    friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)         \
847    {  l.swap(r);  }                                                                             \
848                                                                                                 \
849    inner_allocator_type&       inner_allocator()                                                \
850       { return m_inner; }                                                                       \
851                                                                                                 \
852    inner_allocator_type const& inner_allocator() const                                          \
853       { return m_inner; }                                                                       \
854                                                                                                 \
855    outer_allocator_type      & outer_allocator()                                                \
856       { return static_cast<outer_allocator_type&>(*this); }                                     \
857                                                                                                 \
858    const outer_allocator_type &outer_allocator() const                                          \
859       { return static_cast<const outer_allocator_type&>(*this); }                               \
860                                                                                                 \
861    scoped_allocator_type select_on_container_copy_construction() const                          \
862    {                                                                                            \
863       return scoped_allocator_type                                                              \
864          (internal_type_t()                                                                     \
865          ,outer_traits_type::select_on_container_copy_construction(this->outer_allocator())     \
866          ,inner_traits_type::select_on_container_copy_construction(this->inner_allocator())     \
867          );                                                                                     \
868    }                                                                                            \
869    private:                                                                                     \
870    inner_allocator_type m_inner;                                                                \
871 };                                                                                              \
872 //!
873 #define BOOST_PP_LOCAL_LIMITS (1, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
874 #include BOOST_PP_LOCAL_ITERATE()
875
876 #endif   //#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
877
878 //Specialization for adaptor without any InnerAlloc
879 template <typename OuterAlloc>
880 class scoped_allocator_adaptor_base
881    < OuterAlloc
882    #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
883       , true
884       BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, nat)
885    #endif
886    >
887    : public OuterAlloc
888 {
889    BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor_base)
890    public:
891
892    template <class U>
893    struct rebind_base
894    {
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)
898          , true
899          BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
900          #endif
901          > other;
902    };
903
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;
915
916    scoped_allocator_adaptor_base()
917       {}
918
919    template <class OuterA2>
920    scoped_allocator_adaptor_base(BOOST_FWD_REF(OuterA2) outerAlloc)
921       : outer_allocator_type(::boost::forward<OuterA2>(outerAlloc))
922       {}
923
924    scoped_allocator_adaptor_base(const scoped_allocator_adaptor_base& other)
925       : outer_allocator_type(other.outer_allocator())
926       {}
927
928    scoped_allocator_adaptor_base(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
929       : outer_allocator_type(::boost::move(other.outer_allocator()))
930       {}
931
932    template <class OuterA2>
933    scoped_allocator_adaptor_base
934       (const scoped_allocator_adaptor_base<
935          OuterA2
936          #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
937          , true
938          BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
939          #endif
940          >& other)
941       : outer_allocator_type(other.outer_allocator())
942       {}
943
944    template <class OuterA2>
945    scoped_allocator_adaptor_base
946       (BOOST_RV_REF_BEG scoped_allocator_adaptor_base<
947          OuterA2
948          #if defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
949          , true
950          BOOST_PP_ENUM_TRAILING(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, BOOST_CONTAINER_PP_IDENTITY, container_detail::nat)
951          #endif
952          > BOOST_RV_REF_END other)
953       : outer_allocator_type(other.outer_allocator())
954       {}
955
956    public:
957    struct internal_type_t{};
958
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))
962       {}
963
964    public:
965    scoped_allocator_adaptor_base &operator=(BOOST_COPY_ASSIGN_REF(scoped_allocator_adaptor_base) other)
966    {
967       outer_allocator_type::operator=(other.outer_allocator());
968       return *this;
969    }
970
971    scoped_allocator_adaptor_base &operator=(BOOST_RV_REF(scoped_allocator_adaptor_base) other)
972    {
973       outer_allocator_type::operator=(boost::move(other.outer_allocator()));
974       return *this;
975    }
976
977    void swap(scoped_allocator_adaptor_base &r)
978    {
979       boost::container::swap_dispatch(this->outer_allocator(), r.outer_allocator());
980    }
981
982    friend void swap(scoped_allocator_adaptor_base &l, scoped_allocator_adaptor_base &r)
983    {  l.swap(r);  }
984
985    inner_allocator_type&       inner_allocator()
986       { return static_cast<inner_allocator_type&>(*this); }
987
988    inner_allocator_type const& inner_allocator() const
989       { return static_cast<const inner_allocator_type&>(*this); }
990
991    outer_allocator_type      & outer_allocator()
992       { return static_cast<outer_allocator_type&>(*this); }
993
994    const outer_allocator_type &outer_allocator() const
995       { return static_cast<const outer_allocator_type&>(*this); }
996
997    scoped_allocator_type select_on_container_copy_construction() const
998    {
999       return scoped_allocator_type
1000          (internal_type_t()
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()
1005          );
1006    }
1007 };
1008
1009 }  //namespace container_detail {
1010
1011 #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1012
1013 //Scoped allocator
1014 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1015
1016    #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1017
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.
1023    //!
1024    //! This adaptor is
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.
1036    //!
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]
1040    //!
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>.
1045    //!
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
1052
1053    #else // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1054
1055    template <typename OuterAlloc, typename ...InnerAllocs>
1056    class scoped_allocator_adaptor<OuterAlloc, InnerAllocs...>
1057
1058    #endif   // #if !defined(BOOST_CONTAINER_UNIMPLEMENTED_PACK_EXPANSION_TO_FIXED_LIST)
1059
1060 #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1061
1062 template <typename OuterAlloc
1063          BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1064          >
1065 class scoped_allocator_adaptor
1066 #endif
1067    : public container_detail::scoped_allocator_adaptor_base
1068          <OuterAlloc
1069          #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1070          , InnerAllocs...
1071          #else
1072          , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1073          #endif
1074          >
1075 {
1076    BOOST_COPYABLE_AND_MOVABLE(scoped_allocator_adaptor)
1077
1078    public:
1079    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1080    typedef container_detail::scoped_allocator_adaptor_base
1081       <OuterAlloc
1082       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1083       , InnerAllocs...
1084       #else
1085       , true BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1086       #endif
1087       >                       base_type;
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
1092    //!
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;
1117
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>
1122    template <class U>
1123    struct rebind
1124    {
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)
1128          , InnerAllocs...
1129          #else
1130          BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1131          #endif
1132          > other;
1133    };
1134
1135    //! <b>Effects</b>: value-initializes the OuterAlloc base class
1136    //! and the inner allocator object.
1137    scoped_allocator_adaptor()
1138       {}
1139
1140    ~scoped_allocator_adaptor()
1141       {}
1142
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())
1147       {}
1148
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()))
1153       {}
1154
1155    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1156
1157    //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1158    //!
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...)
1165       {}
1166    #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1167
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)                                           \
1174                   )                                                                             \
1175       {}                                                                                        \
1176    //!
1177    #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1178    #include BOOST_PP_LOCAL_ITERATE()
1179
1180    #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1181
1182    //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1183    //!
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)
1188       , InnerAllocs...
1189       #else
1190       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1191       #endif
1192       > &other)
1193       : base_type(other.base())
1194       {}
1195
1196    //! <b>Requires</b>: OuterAlloc shall be constructible from OuterA2.
1197    //!
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)
1203       , InnerAllocs...
1204       #else
1205       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1206       #endif
1207       > BOOST_RV_REF_END other)
1208       : base_type(::boost::move(other.base()))
1209       {}
1210
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))); }
1213
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)))); }
1216
1217    #ifdef BOOST_CONTAINER_DOXYGEN_INVOKED
1218    //! <b>Effects</b>: swaps *this with r.
1219    //!
1220    void swap(scoped_allocator_adaptor &r);
1221
1222    //! <b>Effects</b>: swaps *this with r.
1223    //!
1224    friend void swap(scoped_allocator_adaptor &l, scoped_allocator_adaptor &r);
1225
1226    //! <b>Returns</b>:
1227    //!   <code>static_cast<OuterAlloc&>(*this)</code>.
1228    outer_allocator_type      & outer_allocator() BOOST_CONTAINER_NOEXCEPT;
1229
1230    //! <b>Returns</b>:
1231    //!   <code>static_cast<const OuterAlloc&>(*this)</code>.
1232    const outer_allocator_type &outer_allocator() const BOOST_CONTAINER_NOEXCEPT;
1233
1234    //! <b>Returns</b>:
1235    //!   *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
1236    inner_allocator_type&       inner_allocator() BOOST_CONTAINER_NOEXCEPT;
1237
1238    //! <b>Returns</b>:
1239    //!   *this if <code>sizeof...(InnerAllocs)</code> is zero; otherwise, inner.
1240    inner_allocator_type const& inner_allocator() const BOOST_CONTAINER_NOEXCEPT;
1241
1242    #endif   //BOOST_CONTAINER_DOXYGEN_INVOKED
1243
1244    //! <b>Returns</b>:
1245    //!   <code>allocator_traits<OuterAlloc>::max_size(outer_allocator())</code>.
1246    size_type max_size() const BOOST_CONTAINER_NOEXCEPT
1247    {
1248       return outer_traits_type::max_size(this->outer_allocator());
1249    }
1250
1251    //! <b>Effects</b>:
1252    //!   calls <code>OUTERMOST_ALLOC_TRAITS(*this)::destroy(OUTERMOST(*this), p)</code>.
1253    template <class T>
1254    void destroy(T* p) BOOST_CONTAINER_NOEXCEPT
1255    {
1256       allocator_traits<typename outermost_allocator<OuterAlloc>::type>
1257          ::destroy(get_outermost_allocator(this->outer_allocator()), p);
1258    }
1259
1260    //! <b>Returns</b>:
1261    //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n)</code>.
1262    pointer allocate(size_type n)
1263    {
1264       return outer_traits_type::allocate(this->outer_allocator(), n);
1265    }
1266
1267    //! <b>Returns</b>:
1268    //! <code>allocator_traits<OuterAlloc>::allocate(outer_allocator(), n, hint)</code>.
1269    pointer allocate(size_type n, const_void_pointer hint)
1270    {
1271       return outer_traits_type::allocate(this->outer_allocator(), n, hint);
1272    }
1273
1274    //! <b>Effects</b>:
1275    //! <code>allocator_traits<OuterAlloc>::deallocate(outer_allocator(), p, n)</code>.
1276    void deallocate(pointer p, size_type n)
1277    {
1278       outer_traits_type::deallocate(this->outer_allocator(), p, n);
1279    }
1280
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
1288
1289    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1290    base_type &base()             { return *this; }
1291
1292    const base_type &base() const { return *this; }
1293    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1294
1295    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1296
1297    //! <b>Effects</b>:
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>.
1301    //!
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>.
1306    //!
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]
1310    //!
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>.
1315    //!
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]
1319    //!
1320    //! 4) Otherwise, the program is ill-formed.
1321    //!
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)
1327    void
1328    #else
1329    typename container_detail::enable_if_c<!container_detail::is_pair<T>::value, void>::type
1330    #endif
1331    construct(T* p, BOOST_FWD_REF(Args)...args)
1332    {
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)...);
1338    }
1339
1340    #else // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1341
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)                                           \
1347             >                                                                                   \
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, _))               \
1350    {                                                                                            \
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, _));                   \
1356    }                                                                                            \
1357    //!
1358    #define BOOST_PP_LOCAL_LIMITS (0, BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS)
1359    #include BOOST_PP_LOCAL_ITERATE()
1360
1361    #endif   // #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1362
1363    template <class T1, class T2>
1364    void construct(std::pair<T1,T2>* p)
1365    {  this->construct_pair(p);  }
1366
1367    template <class T1, class T2>
1368    void construct(container_detail::pair<T1,T2>* p)
1369    {  this->construct_pair(p);  }
1370
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));   }
1374
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));   }
1378
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);   }
1382
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);   }
1387
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);   }
1392
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);   }
1397
1398    #ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1399    private:
1400    template <class Pair>
1401    void construct_pair(Pair* p)
1402    {
1403       this->construct(container_detail::addressof(p->first));
1404       BOOST_TRY{
1405          this->construct(container_detail::addressof(p->second));
1406       }
1407       BOOST_CATCH(...){
1408          this->destroy(container_detail::addressof(p->first));
1409          BOOST_RETHROW
1410       }
1411       BOOST_CATCH_END
1412    }
1413
1414    template <class Pair, class U, class V>
1415    void construct_pair(Pair* p, BOOST_FWD_REF(U) x, BOOST_FWD_REF(V) y)
1416    {
1417       this->construct(container_detail::addressof(p->first), ::boost::forward<U>(x));
1418       BOOST_TRY{
1419          this->construct(container_detail::addressof(p->second), ::boost::forward<V>(y));
1420       }
1421       BOOST_CATCH(...){
1422          this->destroy(container_detail::addressof(p->first));
1423          BOOST_RETHROW
1424       }
1425       BOOST_CATCH_END
1426    }
1427
1428    template <class Pair, class Pair2>
1429    void construct_pair(Pair* p, const Pair2& pr)
1430    {
1431       this->construct(container_detail::addressof(p->first), pr.first);
1432       BOOST_TRY{
1433          this->construct(container_detail::addressof(p->second), pr.second);
1434       }
1435       BOOST_CATCH(...){
1436          this->destroy(container_detail::addressof(p->first));
1437          BOOST_RETHROW
1438       }
1439       BOOST_CATCH_END
1440    }
1441
1442    template <class Pair, class Pair2>
1443    void construct_pair(Pair* p, BOOST_RV_REF(Pair2) pr)
1444    {
1445       this->construct(container_detail::addressof(p->first), ::boost::move(pr.first));
1446       BOOST_TRY{
1447          this->construct(container_detail::addressof(p->second), ::boost::move(pr.second));
1448       }
1449       BOOST_CATCH(...){
1450          this->destroy(container_detail::addressof(p->first));
1451          BOOST_RETHROW
1452       }
1453       BOOST_CATCH_END
1454    }
1455
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);
1458
1459    public:
1460    //Internal function
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)
1464    {}
1465
1466    #endif   //#ifndef BOOST_CONTAINER_DOXYGEN_INVOKED
1467 };
1468
1469 template <typename OuterA1, typename OuterA2
1470    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1471    , typename... InnerAllocs
1472    #else
1473    BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1474    #endif
1475    >
1476 inline bool operator==(
1477    const scoped_allocator_adaptor<OuterA1
1478       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1479       ,InnerAllocs...
1480       #else
1481       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1482       #endif
1483       >& a,
1484    const scoped_allocator_adaptor<OuterA2
1485       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1486       ,InnerAllocs...
1487       #else
1488       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1489       #endif
1490    >& b)
1491 {
1492    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1493    const bool has_zero_inner = sizeof...(InnerAllocs) == 0u;
1494    #else
1495    const bool has_zero_inner =
1496       boost::container::container_detail::is_same
1497          <Q0, container_detail::nat>::value;
1498    #endif
1499
1500     return a.outer_allocator() == b.outer_allocator()
1501         && (has_zero_inner || a.inner_allocator() == b.inner_allocator());
1502 }
1503
1504 template <typename OuterA1, typename OuterA2
1505    #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1506    , typename... InnerAllocs
1507    #else
1508    BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, class Q)
1509    #endif
1510    >
1511 inline bool operator!=(
1512    const scoped_allocator_adaptor<OuterA1
1513       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1514       ,InnerAllocs...
1515       #else
1516       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1517       #endif
1518       >& a,
1519    const scoped_allocator_adaptor<OuterA2
1520       #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) || defined(BOOST_CONTAINER_DOXYGEN_INVOKED)
1521       ,InnerAllocs...
1522       #else
1523       BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_CONTAINER_MAX_CONSTRUCTOR_PARAMETERS, Q)
1524       #endif
1525    >& b)
1526 {
1527     return ! (a == b);
1528 }
1529
1530 }} // namespace boost { namespace container {
1531
1532 #include <boost/container/detail/config_end.hpp>
1533
1534 #endif //  BOOST_CONTAINER_ALLOCATOR_SCOPED_ALLOCATOR_HPP