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