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