xref: /llvm-project/libcxx/include/scoped_allocator (revision b9a2658a3e8bd13b0f9e7a8a440832a95b377216)
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; // removed in C++20
107
108}  // std
109
110*/
111
112#if __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
113#  include <__cxx03/scoped_allocator>
114#else
115#  include <__config>
116#  include <__memory/allocator_traits.h>
117#  include <__memory/uses_allocator_construction.h>
118#  include <__type_traits/common_type.h>
119#  include <__type_traits/enable_if.h>
120#  include <__type_traits/integral_constant.h>
121#  include <__type_traits/is_constructible.h>
122#  include <__type_traits/remove_reference.h>
123#  include <__utility/declval.h>
124#  include <__utility/forward.h>
125#  include <__utility/move.h>
126#  include <__utility/pair.h>
127#  include <__utility/piecewise_construct.h>
128#  include <tuple>
129#  include <version>
130
131#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
132#    pragma GCC system_header
133#  endif
134
135_LIBCPP_PUSH_MACROS
136#  include <__undef_macros>
137
138_LIBCPP_BEGIN_NAMESPACE_STD
139
140#  if !defined(_LIBCPP_CXX03_LANG)
141
142// scoped_allocator_adaptor
143
144template <class... _Allocs>
145class scoped_allocator_adaptor;
146
147template <class... _Allocs>
148struct __get_poc_copy_assignment;
149
150template <class _A0>
151struct __get_poc_copy_assignment<_A0> {
152  static const bool value = allocator_traits<_A0>::propagate_on_container_copy_assignment::value;
153};
154
155template <class _A0, class... _Allocs>
156struct __get_poc_copy_assignment<_A0, _Allocs...> {
157  static const bool value = allocator_traits<_A0>::propagate_on_container_copy_assignment::value ||
158                            __get_poc_copy_assignment<_Allocs...>::value;
159};
160
161template <class... _Allocs>
162struct __get_poc_move_assignment;
163
164template <class _A0>
165struct __get_poc_move_assignment<_A0> {
166  static const bool value = allocator_traits<_A0>::propagate_on_container_move_assignment::value;
167};
168
169template <class _A0, class... _Allocs>
170struct __get_poc_move_assignment<_A0, _Allocs...> {
171  static const bool value = allocator_traits<_A0>::propagate_on_container_move_assignment::value ||
172                            __get_poc_move_assignment<_Allocs...>::value;
173};
174
175template <class... _Allocs>
176struct __get_poc_swap;
177
178template <class _A0>
179struct __get_poc_swap<_A0> {
180  static const bool value = allocator_traits<_A0>::propagate_on_container_swap::value;
181};
182
183template <class _A0, class... _Allocs>
184struct __get_poc_swap<_A0, _Allocs...> {
185  static const bool value =
186      allocator_traits<_A0>::propagate_on_container_swap::value || __get_poc_swap<_Allocs...>::value;
187};
188
189template <class... _Allocs>
190struct __get_is_always_equal;
191
192template <class _A0>
193struct __get_is_always_equal<_A0> {
194  static const bool value = allocator_traits<_A0>::is_always_equal::value;
195};
196
197template <class _A0, class... _Allocs>
198struct __get_is_always_equal<_A0, _Allocs...> {
199  static const bool value = allocator_traits<_A0>::is_always_equal::value && __get_is_always_equal<_Allocs...>::value;
200};
201
202template <class... _Allocs>
203class __scoped_allocator_storage;
204
205template <class _OuterAlloc, class... _InnerAllocs>
206class __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> : public _OuterAlloc {
207  typedef _OuterAlloc outer_allocator_type;
208
209protected:
210  typedef scoped_allocator_adaptor<_InnerAllocs...> inner_allocator_type;
211
212private:
213  inner_allocator_type __inner_;
214
215protected:
216  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage() _NOEXCEPT {}
217
218  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
219  _LIBCPP_HIDE_FROM_ABI
220  __scoped_allocator_storage(_OuterA2&& __outer_alloc, const _InnerAllocs&... __inner_allocs) _NOEXCEPT
221      : outer_allocator_type(std::forward<_OuterA2>(__outer_alloc)),
222        __inner_(__inner_allocs...) {}
223
224  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0>
225  _LIBCPP_HIDE_FROM_ABI
226  __scoped_allocator_storage(const __scoped_allocator_storage<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
227      : outer_allocator_type(__other.outer_allocator()),
228        __inner_(__other.inner_allocator()) {}
229
230  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
231  _LIBCPP_HIDE_FROM_ABI
232  __scoped_allocator_storage(__scoped_allocator_storage<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
233      : outer_allocator_type(std::move(__other.outer_allocator())),
234        __inner_(std::move(__other.inner_allocator())) {}
235
236  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
237  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(_OuterA2&& __o, const inner_allocator_type& __i) _NOEXCEPT
238      : outer_allocator_type(std::forward<_OuterA2>(__o)),
239        __inner_(__i) {}
240
241  _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return __inner_; }
242  _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT { return __inner_; }
243
244  _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT {
245    return static_cast<outer_allocator_type&>(*this);
246  }
247  _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT {
248    return static_cast<const outer_allocator_type&>(*this);
249  }
250
251  scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...> _LIBCPP_HIDE_FROM_ABI
252  select_on_container_copy_construction() const _NOEXCEPT {
253    return scoped_allocator_adaptor<outer_allocator_type, _InnerAllocs...>(
254        allocator_traits<outer_allocator_type>::select_on_container_copy_construction(outer_allocator()),
255        allocator_traits<inner_allocator_type>::select_on_container_copy_construction(inner_allocator()));
256  }
257
258  template <class...>
259  friend class __scoped_allocator_storage;
260};
261
262template <class _OuterAlloc>
263class __scoped_allocator_storage<_OuterAlloc> : public _OuterAlloc {
264  typedef _OuterAlloc outer_allocator_type;
265
266protected:
267  typedef scoped_allocator_adaptor<_OuterAlloc> inner_allocator_type;
268
269  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage() _NOEXCEPT {}
270
271  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
272  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(_OuterA2&& __outer_alloc) _NOEXCEPT
273      : outer_allocator_type(std::forward<_OuterA2>(__outer_alloc)) {}
274
275  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0>
276  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(const __scoped_allocator_storage<_OuterA2>& __other) _NOEXCEPT
277      : outer_allocator_type(__other.outer_allocator()) {}
278
279  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
280  _LIBCPP_HIDE_FROM_ABI __scoped_allocator_storage(__scoped_allocator_storage<_OuterA2>&& __other) _NOEXCEPT
281      : outer_allocator_type(std::move(__other.outer_allocator())) {}
282
283  _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT {
284    return static_cast<inner_allocator_type&>(*this);
285  }
286  _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT {
287    return static_cast<const inner_allocator_type&>(*this);
288  }
289
290  _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT {
291    return static_cast<outer_allocator_type&>(*this);
292  }
293  _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT {
294    return static_cast<const outer_allocator_type&>(*this);
295  }
296
297  _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor<outer_allocator_type>
298  select_on_container_copy_construction() const _NOEXCEPT {
299    return scoped_allocator_adaptor<outer_allocator_type>(
300        allocator_traits<outer_allocator_type>::select_on_container_copy_construction(outer_allocator()));
301  }
302
303  __scoped_allocator_storage(const outer_allocator_type& __o, const inner_allocator_type& __i) _NOEXCEPT;
304
305  template <class...>
306  friend class __scoped_allocator_storage;
307};
308
309// __outermost
310
311template <class _Alloc>
312decltype(std::declval<_Alloc>().outer_allocator(), true_type()) __has_outer_allocator_test(_Alloc&& __a);
313
314template <class _Alloc>
315false_type __has_outer_allocator_test(const volatile _Alloc& __a);
316
317template <class _Alloc>
318struct __has_outer_allocator
319    : public common_type< decltype(std::__has_outer_allocator_test(std::declval<_Alloc&>()))>::type {};
320
321template <class _Alloc, bool = __has_outer_allocator<_Alloc>::value>
322struct __outermost {
323  typedef _Alloc type;
324  _LIBCPP_HIDE_FROM_ABI type& operator()(type& __a) const _NOEXCEPT { return __a; }
325};
326
327template <class _Alloc>
328struct __outermost<_Alloc, true> {
329  typedef __libcpp_remove_reference_t< decltype(std::declval<_Alloc>().outer_allocator()) > _OuterAlloc;
330  typedef typename __outermost<_OuterAlloc>::type type;
331  _LIBCPP_HIDE_FROM_ABI type& operator()(_Alloc& __a) const _NOEXCEPT {
332    return __outermost<_OuterAlloc>()(__a.outer_allocator());
333  }
334};
335
336template <class _OuterAlloc, class... _InnerAllocs>
337class _LIBCPP_TEMPLATE_VIS scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>
338    : public __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> {
339  typedef __scoped_allocator_storage<_OuterAlloc, _InnerAllocs...> _Base;
340  typedef allocator_traits<_OuterAlloc> _OuterTraits;
341
342public:
343  typedef _OuterAlloc outer_allocator_type;
344  typedef typename _Base::inner_allocator_type inner_allocator_type;
345  typedef typename _OuterTraits::size_type size_type;
346  typedef typename _OuterTraits::difference_type difference_type;
347  typedef typename _OuterTraits::pointer pointer;
348  typedef typename _OuterTraits::const_pointer const_pointer;
349  typedef typename _OuterTraits::void_pointer void_pointer;
350  typedef typename _OuterTraits::const_void_pointer const_void_pointer;
351
352  typedef integral_constant< bool, __get_poc_copy_assignment<outer_allocator_type, _InnerAllocs...>::value >
353      propagate_on_container_copy_assignment;
354  typedef integral_constant< bool, __get_poc_move_assignment<outer_allocator_type, _InnerAllocs...>::value >
355      propagate_on_container_move_assignment;
356  typedef integral_constant< bool, __get_poc_swap<outer_allocator_type, _InnerAllocs...>::value >
357      propagate_on_container_swap;
358  typedef integral_constant< bool, __get_is_always_equal<outer_allocator_type, _InnerAllocs...>::value >
359      is_always_equal;
360
361  template <class _Tp>
362  struct rebind {
363    typedef scoped_allocator_adaptor< typename _OuterTraits::template rebind_alloc<_Tp>, _InnerAllocs... > other;
364  };
365
366  _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor() _NOEXCEPT {}
367  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
368  _LIBCPP_HIDE_FROM_ABI
369  scoped_allocator_adaptor(_OuterA2&& __outer_alloc, const _InnerAllocs&... __inner_allocs) _NOEXCEPT
370      : _Base(std::forward<_OuterA2>(__outer_alloc), __inner_allocs...) {}
371  // scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) = default;
372  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, const _OuterA2&>::value, int> = 0>
373  _LIBCPP_HIDE_FROM_ABI
374  scoped_allocator_adaptor(const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __other) _NOEXCEPT
375      : _Base(__other) {}
376  template <class _OuterA2, __enable_if_t<is_constructible<outer_allocator_type, _OuterA2>::value, int> = 0>
377  _LIBCPP_HIDE_FROM_ABI
378  scoped_allocator_adaptor(scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>&& __other) _NOEXCEPT
379      : _Base(std::move(__other)) {}
380
381  // scoped_allocator_adaptor& operator=(const scoped_allocator_adaptor&) = default;
382  // scoped_allocator_adaptor& operator=(scoped_allocator_adaptor&&) = default;
383  // ~scoped_allocator_adaptor() = default;
384
385  _LIBCPP_HIDE_FROM_ABI inner_allocator_type& inner_allocator() _NOEXCEPT { return _Base::inner_allocator(); }
386  _LIBCPP_HIDE_FROM_ABI const inner_allocator_type& inner_allocator() const _NOEXCEPT {
387    return _Base::inner_allocator();
388  }
389
390  _LIBCPP_HIDE_FROM_ABI outer_allocator_type& outer_allocator() _NOEXCEPT { return _Base::outer_allocator(); }
391  _LIBCPP_HIDE_FROM_ABI const outer_allocator_type& outer_allocator() const _NOEXCEPT {
392    return _Base::outer_allocator();
393  }
394
395  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pointer allocate(size_type __n) {
396    return allocator_traits<outer_allocator_type>::allocate(outer_allocator(), __n);
397  }
398  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI pointer allocate(size_type __n, const_void_pointer __hint) {
399    return allocator_traits<outer_allocator_type>::allocate(outer_allocator(), __n, __hint);
400  }
401
402  _LIBCPP_HIDE_FROM_ABI void deallocate(pointer __p, size_type __n) _NOEXCEPT {
403    allocator_traits<outer_allocator_type>::deallocate(outer_allocator(), __p, __n);
404  }
405
406  _LIBCPP_HIDE_FROM_ABI size_type max_size() const {
407    return allocator_traits<outer_allocator_type>::max_size(outer_allocator());
408  }
409
410#    if _LIBCPP_STD_VER >= 20
411  template <class _Type, class... _Args>
412  _LIBCPP_HIDE_FROM_ABI void construct(_Type* __ptr, _Args&&... __args) {
413    using _OM = __outermost<outer_allocator_type>;
414    std::apply(
415        [__ptr, this](auto&&... __newargs) {
416          allocator_traits<typename _OM::type>::construct(
417              _OM()(outer_allocator()), __ptr, std::forward<decltype(__newargs)>(__newargs)...);
418        },
419        std::uses_allocator_construction_args<_Type>(inner_allocator(), std::forward<_Args>(__args)...));
420  }
421#    else
422  template <class _Tp, class... _Args>
423  _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Args&&... __args) {
424    __construct(__uses_alloc_ctor<_Tp, inner_allocator_type&, _Args...>(), __p, std::forward<_Args>(__args)...);
425  }
426
427  template <class _T1, class _T2, class... _Args1, class... _Args2>
428  _LIBCPP_HIDE_FROM_ABI void
429  construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) {
430    typedef __outermost<outer_allocator_type> _OM;
431    allocator_traits<typename _OM::type>::construct(
432        _OM()(outer_allocator()),
433        __p,
434        piecewise_construct,
435        __transform_tuple(typename __uses_alloc_ctor< _T1, inner_allocator_type&, _Args1... >::type(),
436                          std::move(__x),
437                          typename __make_tuple_indices<sizeof...(_Args1)>::type{}),
438        __transform_tuple(typename __uses_alloc_ctor< _T2, inner_allocator_type&, _Args2... >::type(),
439                          std::move(__y),
440                          typename __make_tuple_indices<sizeof...(_Args2)>::type{}));
441  }
442
443  template <class _T1, class _T2>
444  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) {
445    construct(__p, piecewise_construct, tuple<>{}, tuple<>{});
446  }
447
448  template <class _T1, class _T2, class _Up, class _Vp>
449  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) {
450    construct(__p,
451              piecewise_construct,
452              std::forward_as_tuple(std::forward<_Up>(__x)),
453              std::forward_as_tuple(std::forward<_Vp>(__y)));
454  }
455
456  template <class _T1, class _T2, class _Up, class _Vp>
457  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) {
458    construct(__p, piecewise_construct, std::forward_as_tuple(__x.first), std::forward_as_tuple(__x.second));
459  }
460
461  template <class _T1, class _T2, class _Up, class _Vp>
462  _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) {
463    construct(__p,
464              piecewise_construct,
465              std::forward_as_tuple(std::forward<_Up>(__x.first)),
466              std::forward_as_tuple(std::forward<_Vp>(__x.second)));
467  }
468#    endif
469
470  template <class _Tp>
471  _LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) {
472    typedef __outermost<outer_allocator_type> _OM;
473    allocator_traits<typename _OM::type>::destroy(_OM()(outer_allocator()), __p);
474  }
475
476  _LIBCPP_HIDE_FROM_ABI scoped_allocator_adaptor select_on_container_copy_construction() const _NOEXCEPT {
477    return _Base::select_on_container_copy_construction();
478  }
479
480private:
481  _LIBCPP_HIDE_FROM_ABI explicit scoped_allocator_adaptor(
482      outer_allocator_type&& __o, inner_allocator_type&& __i) _NOEXCEPT : _Base(std::move(__o), std::move(__i)) {}
483
484  template <class _Tp, class... _Args>
485  _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 0>, _Tp* __p, _Args&&... __args) {
486    typedef __outermost<outer_allocator_type> _OM;
487    allocator_traits<typename _OM::type>::construct(_OM()(outer_allocator()), __p, std::forward<_Args>(__args)...);
488  }
489
490  template <class _Tp, class... _Args>
491  _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 1>, _Tp* __p, _Args&&... __args) {
492    typedef __outermost<outer_allocator_type> _OM;
493    allocator_traits<typename _OM::type>::construct(
494        _OM()(outer_allocator()), __p, allocator_arg, inner_allocator(), std::forward<_Args>(__args)...);
495  }
496
497  template <class _Tp, class... _Args>
498  _LIBCPP_HIDE_FROM_ABI void __construct(integral_constant<int, 2>, _Tp* __p, _Args&&... __args) {
499    typedef __outermost<outer_allocator_type> _OM;
500    allocator_traits<typename _OM::type>::construct(
501        _OM()(outer_allocator()), __p, std::forward<_Args>(__args)..., inner_allocator());
502  }
503
504  template <class... _Args, size_t... _Idx>
505  _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...>
506  __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) {
507    return std::forward_as_tuple(std::get<_Idx>(std::move(__t))...);
508  }
509
510  template <class... _Args, size_t... _Idx>
511  _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>
512  __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) {
513    using _Tup = tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>;
514    return _Tup(allocator_arg, inner_allocator(), std::get<_Idx>(std::move(__t))...);
515  }
516
517  template <class... _Args, size_t... _Idx>
518  _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., inner_allocator_type&>
519  __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Idx...>) {
520    using _Tup = tuple<_Args&&..., inner_allocator_type&>;
521    return _Tup(std::get<_Idx>(std::move(__t))..., inner_allocator());
522  }
523
524  template <class...>
525  friend class __scoped_allocator_storage;
526};
527
528#    if _LIBCPP_STD_VER >= 17
529template <class _OuterAlloc, class... _InnerAllocs>
530scoped_allocator_adaptor(_OuterAlloc, _InnerAllocs...) -> scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs...>;
531#    endif
532
533template <class _OuterA1, class _OuterA2>
534inline _LIBCPP_HIDE_FROM_ABI bool
535operator==(const scoped_allocator_adaptor<_OuterA1>& __a, const scoped_allocator_adaptor<_OuterA2>& __b) _NOEXCEPT {
536  return __a.outer_allocator() == __b.outer_allocator();
537}
538
539template <class _OuterA1, class _OuterA2, class _InnerA0, class... _InnerAllocs>
540inline _LIBCPP_HIDE_FROM_ABI bool
541operator==(const scoped_allocator_adaptor<_OuterA1, _InnerA0, _InnerAllocs...>& __a,
542           const scoped_allocator_adaptor<_OuterA2, _InnerA0, _InnerAllocs...>& __b) _NOEXCEPT {
543  return __a.outer_allocator() == __b.outer_allocator() && __a.inner_allocator() == __b.inner_allocator();
544}
545
546#    if _LIBCPP_STD_VER <= 17
547
548template <class _OuterA1, class _OuterA2, class... _InnerAllocs>
549inline _LIBCPP_HIDE_FROM_ABI bool operator!=(const scoped_allocator_adaptor<_OuterA1, _InnerAllocs...>& __a,
550                                             const scoped_allocator_adaptor<_OuterA2, _InnerAllocs...>& __b) _NOEXCEPT {
551  return !(__a == __b);
552}
553
554#    endif // _LIBCPP_STD_VER <= 17
555
556#  endif // !defined(_LIBCPP_CXX03_LANG)
557
558_LIBCPP_END_NAMESPACE_STD
559
560_LIBCPP_POP_MACROS
561
562#  if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
563#    include <atomic>
564#    include <climits>
565#    include <concepts>
566#    include <cstring>
567#    include <ctime>
568#    include <iterator>
569#    include <memory>
570#    include <ratio>
571#    include <stdexcept>
572#    include <type_traits>
573#    include <variant>
574#  endif
575#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
576
577#endif // _LIBCPP_SCOPED_ALLOCATOR
578