1// -*- C++ -*-
2//===-------------------------- scoped_allocator --------------------------===//
3//
4// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5// See https://llvm.org/LICENSE.txt for license information.
6// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7//
8//===----------------------------------------------------------------------===//
9
10#ifndef _LIBCPP_SCOPED_ALLOCATOR
11#define _LIBCPP_SCOPED_ALLOCATOR
12
13/*
14    scoped_allocator synopsis
15
16namespace std
17{
18
19template <class OuterAlloc, class... InnerAllocs>
20class scoped_allocator_adaptor : public OuterAlloc
21{
22    typedef allocator_traits<OuterAlloc> OuterTraits; // exposition only
23    scoped_allocator_adaptor<InnerAllocs...> inner;   // exposition only
24public:
25
26    typedef OuterAlloc outer_allocator_type;
27    typedef see below inner_allocator_type;
28
29    typedef typename OuterTraits::value_type value_type;
30    typedef typename OuterTraits::size_type size_type;
31    typedef typename OuterTraits::difference_type difference_type;
32    typedef typename OuterTraits::pointer pointer;
33    typedef typename OuterTraits::const_pointer const_pointer;
34    typedef typename OuterTraits::void_pointer void_pointer;
35    typedef typename OuterTraits::const_void_pointer const_void_pointer;
36
37    typedef see below propagate_on_container_copy_assignment;
38    typedef see below propagate_on_container_move_assignment;
39    typedef see below propagate_on_container_swap;
40    typedef see below is_always_equal;
41
42    template <class Tp>
43        struct rebind
44        {
45            typedef scoped_allocator_adaptor<
46                OuterTraits::template rebind_alloc<Tp>, InnerAllocs...> other;
47        };
48
49    scoped_allocator_adaptor();
50    template <class OuterA2>
51        scoped_allocator_adaptor(OuterA2&& outerAlloc,
52                                 const InnerAllocs&... innerAllocs) noexcept;
53    scoped_allocator_adaptor(const scoped_allocator_adaptor& other) noexcept;
54    scoped_allocator_adaptor(scoped_allocator_adaptor&& other) noexcept;
55    template <class OuterA2>
56        scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& other) noexcept;
57    template <class OuterA2>
58        scoped_allocator_adaptor(const scoped_allocator_adaptor<OuterA2, InnerAllocs...>&& other) noexcept;
59
60    scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
61    scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
62    ~scoped_allocator_adaptor();
63
64    inner_allocator_type& inner_allocator() noexcept;
65    const inner_allocator_type& inner_allocator() const noexcept;
66
67    outer_allocator_type& outer_allocator() noexcept;
68    const outer_allocator_type& outer_allocator() const noexcept;
69
70    pointer allocate(size_type n);                           // [[nodiscard]] in C++20
71    pointer allocate(size_type n, const_void_pointer hint);  // [[nodiscard]] in C++20
72    void deallocate(pointer p, size_type n) noexcept;
73
74    size_type max_size() const;
75    template <class T, class... Args> void construct(T* p, Args&& args);
76    template <class T1, class T2, class... Args1, class... Args2>
77        void construct(pair<T1, T2>* p, piecewise_construct t, tuple<Args1...> x,
78                       tuple<Args2...> y);
79    template <class T1, class T2>
80        void construct(pair<T1, T2>* p);
81    template <class T1, class T2, class U, class V>
82        void construct(pair<T1, T2>* p, U&& x, V&& y);
83    template <class T1, class T2, class U, class V>
84        void construct(pair<T1, T2>* p, const pair<U, V>& x);
85    template <class T1, class T2, class U, class V>
86        void construct(pair<T1, T2>* p, pair<U, V>&& x);
87    template <class T> void destroy(T* p);
88
89    template <class T> void destroy(T* p) noexcept;
90
91    scoped_allocator_adaptor select_on_container_copy_construction() const noexcept;
92};
93
94template <class OuterA1, class OuterA2, class... InnerAllocs>
95    bool
96    operator==(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
97               const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
98
99template <class OuterA1, class OuterA2, class... InnerAllocs>
100    bool
101    operator!=(const scoped_allocator_adaptor<OuterA1, InnerAllocs...>& a,
102               const scoped_allocator_adaptor<OuterA2, InnerAllocs...>& b) noexcept;
103
104}  // std
105
106*/
107
108#include <__config>
109#include <memory>
110#include <version>
111
112#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
113#pragma GCC system_header
114#endif
115
116_LIBCPP_BEGIN_NAMESPACE_STD
117
118#if !defined(_LIBCPP_CXX03_LANG)
119
120// scoped_allocator_adaptor
121
122template <class ..._Allocs>
123class scoped_allocator_adaptor;
124
125template <class ..._Allocs> struct __get_poc_copy_assignment;
126
127template <class _A0>
128struct __get_poc_copy_assignment<_A0>
129{
130    static const bool value = allocator_traits<_A0>::
131                              propagate_on_container_copy_assignment::value;
132};
133
134template <class _A0, class ..._Allocs>
135struct __get_poc_copy_assignment<_A0, _Allocs...>
136{
137    static const bool value =
138        allocator_traits<_A0>::propagate_on_container_copy_assignment::value ||
139        __get_poc_copy_assignment<_Allocs...>::value;
140};
141
142template <class ..._Allocs> struct __get_poc_move_assignment;
143
144template <class _A0>
145struct __get_poc_move_assignment<_A0>
146{
147    static const bool value = allocator_traits<_A0>::
148                              propagate_on_container_move_assignment::value;
149};
150
151template <class _A0, class ..._Allocs>
152struct __get_poc_move_assignment<_A0, _Allocs...>
153{
154    static const bool value =
155        allocator_traits<_A0>::propagate_on_container_move_assignment::value ||
156        __get_poc_move_assignment<_Allocs...>::value;
157};
158
159template <class ..._Allocs> struct __get_poc_swap;
160
161template <class _A0>
162struct __get_poc_swap<_A0>
163{
164    static const bool value = allocator_traits<_A0>::
165                              propagate_on_container_swap::value;
166};
167
168template <class _A0, class ..._Allocs>
169struct __get_poc_swap<_A0, _Allocs...>
170{
171    static const bool value =
172        allocator_traits<_A0>::propagate_on_container_swap::value ||
173        __get_poc_swap<_Allocs...>::value;
174};
175
176template <class ..._Allocs> struct __get_is_always_equal;
177
178template <class _A0>
179struct __get_is_always_equal<_A0>
180{
181    static const bool value = allocator_traits<_A0>::is_always_equal::value;
182};
183
184template <class _A0, class ..._Allocs>
185struct __get_is_always_equal<_A0, _Allocs...>
186{
187    static const bool value =
188        allocator_traits<_A0>::is_always_equal::value &&
189        __get_is_always_equal<_Allocs...>::value;
190};
191
192template <class ..._Allocs>
193class __scoped_allocator_storage;
194
195template <class _OuterAlloc, class... _InnerAllocs>
196class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
197    : public _OuterAlloc
198{
199    typedef _OuterAlloc outer_allocator_type;
200protected:
201    typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
202
203private:
204    inner_allocator_type __inner_;
205
206protected:
207
208    _LIBCPP_INLINE_VISIBILITY
209    __scoped_allocator_storage() _NOEXCEPT {}
210
211    template <class _OuterA2,
212              class = typename enable_if<
213                        is_constructible<outer_allocator_type, _OuterA2>::value
214                      >::type>
215        _LIBCPP_INLINE_VISIBILITY
216        __scoped_allocator_storage(_OuterA2&& __outerAlloc,
217                                   const _InnerAllocs& ...__innerAllocs) _NOEXCEPT
218            : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)),
219              __inner_(__innerAllocs...) {}
220
221    template <class _OuterA2,
222              class = typename enable_if<
223                        is_constructible<outer_allocator_type, const _OuterA2&>::value
224                      >::type>
225        _LIBCPP_INLINE_VISIBILITY
226        __scoped_allocator_storage(
227            const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
228            : outer_allocator_type(__other.outer_allocator()),
229              __inner_(__other.inner_allocator()) {}
230
231    template <class _OuterA2,
232              class = typename enable_if<
233                        is_constructible<outer_allocator_type, _OuterA2>::value
234                      >::type>
235        _LIBCPP_INLINE_VISIBILITY
236        __scoped_allocator_storage(
237            __scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
238            : outer_allocator_type(_VSTD::move(__other.outer_allocator())),
239              __inner_(_VSTD::move(__other.inner_allocator())) {}
240
241    template <class _OuterA2,
242              class = typename enable_if<
243                        is_constructible<outer_allocator_type, _OuterA2>::value
244                      >::type>
245        _LIBCPP_INLINE_VISIBILITY
246        __scoped_allocator_storage(_OuterA2&& __o,
247                                   const inner_allocator_type& __i) _NOEXCEPT
248            : outer_allocator_type(_VSTD::forward<_OuterA2>(__o)),
249              __inner_(__i)
250        {
251        }
252
253    _LIBCPP_INLINE_VISIBILITY
254    inner_allocator_type& inner_allocator() _NOEXCEPT             {return __inner_;}
255    _LIBCPP_INLINE_VISIBILITY
256    const inner_allocator_type& inner_allocator() const _NOEXCEPT {return __inner_;}
257
258    _LIBCPP_INLINE_VISIBILITY
259    outer_allocator_type& outer_allocator() _NOEXCEPT
260        {return static_cast<outer_allocator_type&>(*this);}
261    _LIBCPP_INLINE_VISIBILITY
262    const outer_allocator_type& outer_allocator() const _NOEXCEPT
263        {return static_cast<const outer_allocator_type&>(*this);}
264
265    scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
266    _LIBCPP_INLINE_VISIBILITY
267    select_on_container_copy_construction() const _NOEXCEPT
268        {
269            return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>
270            (
271                allocator_traits<outer_allocator_type>::
272                    select_on_container_copy_construction(outer_allocator()),
273                allocator_traits<inner_allocator_type>::
274                    select_on_container_copy_construction(inner_allocator())
275            );
276        }
277
278    template <class...> friend class __scoped_allocator_storage;
279};
280
281template <class _OuterAlloc>
282class __scoped_allocator_storage<_OuterAlloc>
283    : public _OuterAlloc
284{
285    typedef _OuterAlloc outer_allocator_type;
286protected:
287    typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type;
288
289    _LIBCPP_INLINE_VISIBILITY
290    __scoped_allocator_storage() _NOEXCEPT {}
291
292    template <class _OuterA2,
293              class = typename enable_if<
294                        is_constructible<outer_allocator_type, _OuterA2>::value
295                      >::type>
296        _LIBCPP_INLINE_VISIBILITY
297        __scoped_allocator_storage(_OuterA2&& __outerAlloc) _NOEXCEPT
298            : outer_allocator_type(_VSTD::forward<_OuterA2>(__outerAlloc)) {}
299
300    template <class _OuterA2,
301              class = typename enable_if<
302                        is_constructible<outer_allocator_type, const _OuterA2&>::value
303                      >::type>
304        _LIBCPP_INLINE_VISIBILITY
305        __scoped_allocator_storage(
306            const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT
307            : outer_allocator_type(__other.outer_allocator()) {}
308
309    template <class _OuterA2,
310              class = typename enable_if<
311                        is_constructible<outer_allocator_type, _OuterA2>::value
312                      >::type>
313        _LIBCPP_INLINE_VISIBILITY
314        __scoped_allocator_storage(
315            __scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT
316            : outer_allocator_type(_VSTD::move(__other.outer_allocator())) {}
317
318    _LIBCPP_INLINE_VISIBILITY
319    inner_allocator_type& inner_allocator() _NOEXCEPT
320        {return static_cast<inner_allocator_type&>(*this);}
321    _LIBCPP_INLINE_VISIBILITY
322    const inner_allocator_type& inner_allocator() const _NOEXCEPT
323        {return static_cast<const inner_allocator_type&>(*this);}
324
325    _LIBCPP_INLINE_VISIBILITY
326    outer_allocator_type& outer_allocator() _NOEXCEPT
327        {return static_cast<outer_allocator_type&>(*this);}
328    _LIBCPP_INLINE_VISIBILITY
329    const outer_allocator_type& outer_allocator() const _NOEXCEPT
330        {return static_cast<const outer_allocator_type&>(*this);}
331
332    _LIBCPP_INLINE_VISIBILITY
333    scoped_allocator_adaptor<outer_allocator_type>
334    select_on_container_copy_construction() const _NOEXCEPT
335        {return scoped_allocator_adaptor<outer_allocator_type>(
336            allocator_traits<outer_allocator_type>::
337                select_on_container_copy_construction(outer_allocator())
338        );}
339
340    __scoped_allocator_storage(const outer_allocator_type& __o,
341                               const inner_allocator_type& __i) _NOEXCEPT;
342
343    template <class...> friend class __scoped_allocator_storage;
344};
345
346// __outermost
347
348template <class _Alloc>
349decltype(declval<_Alloc>().outer_allocator(), true_type())
350__has_outer_allocator_test(_Alloc&& __a);
351
352template <class _Alloc>
353false_type
354__has_outer_allocator_test(const volatile _Alloc& __a);
355
356template <class _Alloc>
357struct __has_outer_allocator
358    : public common_type
359             <
360                 decltype(__has_outer_allocator_test(declval<_Alloc&>()))
361             >::type
362{
363};
364
365template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
366struct __outermost
367{
368    typedef _Alloc type;
369    _LIBCPP_INLINE_VISIBILITY
370    type& operator()(type& __a) const _NOEXCEPT {return __a;}
371};
372
373template <class _Alloc>
374struct __outermost<_Alloc, true>
375{
376    typedef typename remove_reference
377                     <
378                        decltype(_VSTD::declval<_Alloc>().outer_allocator())
379                     >::type                                    _OuterAlloc;
380    typedef typename __outermost<_OuterAlloc>::type             type;
381    _LIBCPP_INLINE_VISIBILITY
382    type& operator()(_Alloc& __a) const _NOEXCEPT
383        {return __outermost<_OuterAlloc>()(__a.outer_allocator());}
384};
385
386template <class _OuterAlloc, class... _InnerAllocs>
387class _LIBCPP_TEMPLATE_VIS scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
388    : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...>
389{
390    typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> base;
391    typedef allocator_traits<_OuterAlloc>             _OuterTraits;
392public:
393    typedef _OuterAlloc                               outer_allocator_type;
394    typedef typename base::inner_allocator_type       inner_allocator_type;
395    typedef typename _OuterTraits::size_type          size_type;
396    typedef typename _OuterTraits::difference_type    difference_type;
397    typedef typename _OuterTraits::pointer            pointer;
398    typedef typename _OuterTraits::const_pointer      const_pointer;
399    typedef typename _OuterTraits::void_pointer       void_pointer;
400    typedef typename _OuterTraits::const_void_pointer const_void_pointer;
401
402    typedef integral_constant
403            <
404                bool,
405                __get_poc_copy_assignment<outer_allocator_type,
406                                          _InnerAllocs...>::value
407            > propagate_on_container_copy_assignment;
408    typedef integral_constant
409            <
410                bool,
411                __get_poc_move_assignment<outer_allocator_type,
412                                          _InnerAllocs...>::value
413            > propagate_on_container_move_assignment;
414    typedef integral_constant
415            <
416                bool,
417                __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value
418            > propagate_on_container_swap;
419    typedef integral_constant
420            <
421                bool,
422                __get_is_always_equal<outer_allocator_type, _InnerAllocs...>::value
423            > is_always_equal;
424
425    template <class _Tp>
426    struct rebind
427    {
428        typedef scoped_allocator_adaptor
429        <
430            typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs...
431        > other;
432    };
433
434    _LIBCPP_INLINE_VISIBILITY
435    scoped_allocator_adaptor() _NOEXCEPT {}
436    template <class _OuterA2,
437              class = typename enable_if<
438                        is_constructible<outer_allocator_type, _OuterA2>::value
439                      >::type>
440        _LIBCPP_INLINE_VISIBILITY
441        scoped_allocator_adaptor(_OuterA2&& __outerAlloc,
442                                 const _InnerAllocs& ...__innerAllocs) _NOEXCEPT
443            : base(_VSTD::forward<_OuterA2>(__outerAlloc), __innerAllocs...) {}
444    // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default;
445    template <class _OuterA2,
446              class = typename enable_if<
447                        is_constructible<outer_allocator_type, const _OuterA2&>::value
448                      >::type>
449        _LIBCPP_INLINE_VISIBILITY
450        scoped_allocator_adaptor(
451            const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
452                : base(__other) {}
453    template <class _OuterA2,
454              class = typename enable_if<
455                        is_constructible<outer_allocator_type, _OuterA2>::value
456                      >::type>
457        _LIBCPP_INLINE_VISIBILITY
458        scoped_allocator_adaptor(
459            scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
460                : base(_VSTD::move(__other)) {}
461
462    // scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
463    // scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
464    // ~scoped_allocator_adaptor() = default;
465
466    _LIBCPP_INLINE_VISIBILITY
467    inner_allocator_type& inner_allocator() _NOEXCEPT
468        {return base::inner_allocator();}
469    _LIBCPP_INLINE_VISIBILITY
470    const inner_allocator_type& inner_allocator() const _NOEXCEPT
471        {return base::inner_allocator();}
472
473    _LIBCPP_INLINE_VISIBILITY
474    outer_allocator_type& outer_allocator() _NOEXCEPT
475        {return base::outer_allocator();}
476    _LIBCPP_INLINE_VISIBILITY
477    const outer_allocator_type& outer_allocator() const _NOEXCEPT
478        {return base::outer_allocator();}
479
480    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
481    pointer allocate(size_type __n)
482        {return allocator_traits<outer_allocator_type>::
483            allocate(outer_allocator(), __n);}
484    _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY
485    pointer allocate(size_type __n, const_void_pointer __hint)
486        {return allocator_traits<outer_allocator_type>::
487            allocate(outer_allocator(), __n, __hint);}
488
489    _LIBCPP_INLINE_VISIBILITY
490    void deallocate(pointer __p, size_type __n) _NOEXCEPT
491        {allocator_traits<outer_allocator_type>::
492            deallocate(outer_allocator(), __p, __n);}
493
494    _LIBCPP_INLINE_VISIBILITY
495    size_type max_size() const
496        {return allocator_traits<outer_allocator_type>::max_size(outer_allocator());}
497
498    template <class _Tp, class... _Args>
499        _LIBCPP_INLINE_VISIBILITY
500        void construct(_Tp* __p, _Args&& ...__args)
501            {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type&, _Args...>(),
502                         __p, _VSTD::forward<_Args>(__args)...);}
503
504    template <class _T1, class _T2, class... _Args1, class... _Args2>
505    void construct(pair<_T1, _T2>* __p, piecewise_construct_t,
506                       tuple<_Args1...> __x, tuple<_Args2...> __y)
507    {
508        typedef __outermost<outer_allocator_type> _OM;
509        allocator_traits<typename _OM::type>::construct(
510            _OM()(outer_allocator()), __p, piecewise_construct
511          , __transform_tuple(
512              typename __uses_alloc_ctor<
513                  _T1, inner_allocator_type&, _Args1...
514              >::type()
515            , _VSTD::move(__x)
516            , typename __make_tuple_indices<sizeof...(_Args1)>::type{}
517          )
518          , __transform_tuple(
519              typename __uses_alloc_ctor<
520                  _T2, inner_allocator_type&, _Args2...
521              >::type()
522            , _VSTD::move(__y)
523            , typename __make_tuple_indices<sizeof...(_Args2)>::type{}
524          )
525        );
526    }
527
528    template <class _T1, class _T2>
529    void construct(pair<_T1, _T2>* __p)
530    { construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); }
531
532    template <class _T1, class _T2, class _Up, class _Vp>
533    void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) {
534        construct(__p, piecewise_construct,
535                  _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x)),
536                  _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__y)));
537    }
538
539    template <class _T1, class _T2, class _Up, class _Vp>
540    void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) {
541        construct(__p, piecewise_construct,
542                  _VSTD::forward_as_tuple(__x.first),
543                  _VSTD::forward_as_tuple(__x.second));
544    }
545
546    template <class _T1, class _T2, class _Up, class _Vp>
547    void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) {
548        construct(__p, piecewise_construct,
549                  _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x.first)),
550                  _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__x.second)));
551    }
552
553    template <class _Tp>
554        _LIBCPP_INLINE_VISIBILITY
555        void destroy(_Tp* __p)
556            {
557                typedef __outermost<outer_allocator_type> _OM;
558                allocator_traits<typename _OM::type>::
559                                         destroy(_OM()(outer_allocator()), __p);
560            }
561
562    _LIBCPP_INLINE_VISIBILITY
563    scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT
564        {return base::select_on_container_copy_construction();}
565
566private:
567
568
569    template <class _OuterA2,
570              class = typename enable_if<
571                        is_constructible<outer_allocator_type, _OuterA2>::value
572                      >::type>
573    _LIBCPP_INLINE_VISIBILITY
574    scoped_allocator_adaptor(_OuterA2&& __o,
575                             const inner_allocator_type& __i) _NOEXCEPT
576        : base(_VSTD::forward<_OuterA2>(__o), __i) {}
577
578    template <class _Tp, class... _Args>
579        _LIBCPP_INLINE_VISIBILITY
580        void __construct(integral_constant<int, 0>, _Tp* __p, _Args&& ...__args)
581            {
582                typedef __outermost<outer_allocator_type> _OM;
583                allocator_traits<typename _OM::type>::construct
584                (
585                    _OM()(outer_allocator()),
586                    __p,
587                    _VSTD::forward<_Args>(__args)...
588                );
589            }
590
591    template <class _Tp, class... _Args>
592        _LIBCPP_INLINE_VISIBILITY
593        void __construct(integral_constant<int, 1>, _Tp* __p, _Args&& ...__args)
594            {
595                typedef __outermost<outer_allocator_type> _OM;
596                allocator_traits<typename _OM::type>::construct
597                (
598                    _OM()(outer_allocator()),
599                    __p, allocator_arg, inner_allocator(),
600                    _VSTD::forward<_Args>(__args)...
601                );
602            }
603
604    template <class _Tp, class... _Args>
605        _LIBCPP_INLINE_VISIBILITY
606        void __construct(integral_constant<int, 2>, _Tp* __p, _Args&& ...__args)
607            {
608                typedef __outermost<outer_allocator_type> _OM;
609                allocator_traits<typename _OM::type>::construct
610                (
611                    _OM()(outer_allocator()),
612                    __p,
613                    _VSTD::forward<_Args>(__args)...,
614                    inner_allocator()
615                );
616            }
617
618    template <class ..._Args, size_t ..._Idx>
619    _LIBCPP_INLINE_VISIBILITY
620    tuple<_Args&&...>
621    __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t,
622                      __tuple_indices<_Idx...>)
623    {
624        return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...);
625    }
626
627    template <class ..._Args, size_t ..._Idx>
628    _LIBCPP_INLINE_VISIBILITY
629    tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>
630    __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t,
631                      __tuple_indices<_Idx...>)
632    {
633        using _Tup = tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>;
634        return _Tup(allocator_arg, inner_allocator(),
635                    _VSTD::get<_Idx>(_VSTD::move(__t))...);
636    }
637
638    template <class ..._Args, size_t ..._Idx>
639    _LIBCPP_INLINE_VISIBILITY
640    tuple<_Args&&..., inner_allocator_type&>
641    __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t,
642                      __tuple_indices<_Idx...>)
643    {
644        using _Tup = tuple<_Args&&..., inner_allocator_type&>;
645        return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., inner_allocator());
646    }
647
648    template <class...> friend class __scoped_allocator_storage;
649};
650
651template <class _OuterA1, class _OuterA2>
652inline _LIBCPP_INLINE_VISIBILITY
653bool
654operator==(const scoped_allocator_adaptor<_OuterA1>& __a,
655           const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT
656{
657    return __a.outer_allocator() == __b.outer_allocator();
658}
659
660template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs>
661inline _LIBCPP_INLINE_VISIBILITY
662bool
663operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a,
664           const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT
665{
666    return __a.outer_allocator() == __b.outer_allocator() &&
667           __a.inner_allocator() == __b.inner_allocator();
668}
669
670template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
671inline _LIBCPP_INLINE_VISIBILITY
672bool
673operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
674           const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT
675{
676    return !(__a == __b);
677}
678
679#endif  // !defined(_LIBCPP_CXX03_LANG)
680
681_LIBCPP_END_NAMESPACE_STD
682
683#endif  // _LIBCPP_SCOPED_ALLOCATOR
684