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