xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/std/scoped_allocator (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
148fb7bfaSmrg// <scoped_allocator> -*- C++ -*-
248fb7bfaSmrg
3b1e83836Smrg// Copyright (C) 2011-2022 Free Software Foundation, Inc.
448fb7bfaSmrg//
548fb7bfaSmrg// This file is part of the GNU ISO C++ Library.  This library is free
648fb7bfaSmrg// software; you can redistribute it and/or modify it under the
748fb7bfaSmrg// terms of the GNU General Public License as published by the
848fb7bfaSmrg// Free Software Foundation; either version 3, or (at your option)
948fb7bfaSmrg// any later version.
1048fb7bfaSmrg
1148fb7bfaSmrg// This library is distributed in the hope that it will be useful,
1248fb7bfaSmrg// but WITHOUT ANY WARRANTY; without even the implied warranty of
1348fb7bfaSmrg// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1448fb7bfaSmrg// GNU General Public License for more details.
1548fb7bfaSmrg
1648fb7bfaSmrg// Under Section 7 of GPL version 3, you are granted additional
1748fb7bfaSmrg// permissions described in the GCC Runtime Library Exception, version
1848fb7bfaSmrg// 3.1, as published by the Free Software Foundation.
1948fb7bfaSmrg
2048fb7bfaSmrg// You should have received a copy of the GNU General Public License and
2148fb7bfaSmrg// a copy of the GCC Runtime Library Exception along with this program;
2248fb7bfaSmrg// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
2348fb7bfaSmrg// <http://www.gnu.org/licenses/>.
2448fb7bfaSmrg
2548fb7bfaSmrg/** @file include/scoped_allocator
2648fb7bfaSmrg *  This is a Standard C++ Library header.
2748fb7bfaSmrg */
2848fb7bfaSmrg
2948fb7bfaSmrg#ifndef _SCOPED_ALLOCATOR
3048fb7bfaSmrg#define _SCOPED_ALLOCATOR 1
3148fb7bfaSmrg
3248fb7bfaSmrg#pragma GCC system_header
3348fb7bfaSmrg
3448fb7bfaSmrg#if __cplusplus < 201103L
3548fb7bfaSmrg# include <bits/c++0x_warning.h>
3648fb7bfaSmrg#else
3748fb7bfaSmrg
3848fb7bfaSmrg#include <tuple>
3948fb7bfaSmrg#include <bits/alloc_traits.h>
40b1e83836Smrg#include <bits/stl_pair.h>
41b1e83836Smrg#include <bits/uses_allocator.h>
42b1e83836Smrg#if __cplusplus > 201703L
43b1e83836Smrg# include <bits/uses_allocator_args.h>
44b1e83836Smrg#endif
4548fb7bfaSmrg
4648fb7bfaSmrgnamespace std _GLIBCXX_VISIBILITY(default)
4748fb7bfaSmrg{
4848fb7bfaSmrg_GLIBCXX_BEGIN_NAMESPACE_VERSION
4948fb7bfaSmrg
5048fb7bfaSmrg  /**
5148fb7bfaSmrg   * @addtogroup allocators
5248fb7bfaSmrg   * @{
5348fb7bfaSmrg   */
5448fb7bfaSmrg
55b1e83836Smrg  template<typename _OuterAlloc, typename... _InnerAllocs>
56b1e83836Smrg    class scoped_allocator_adaptor;
57b1e83836Smrg
58fb8a8121Smrg  /// @cond undocumented
59fb8a8121Smrg
6048fb7bfaSmrg  template<typename _Alloc>
613f4ceed9Smrg    using __outer_allocator_t
623f4ceed9Smrg      = decltype(std::declval<_Alloc>().outer_allocator());
633f4ceed9Smrg
643f4ceed9Smrg  template<typename _Alloc, typename = void>
653f4ceed9Smrg    struct __outermost_type
663f4ceed9Smrg    {
673f4ceed9Smrg      using type = _Alloc;
68*0a307195Smrg      static type& _S_outermost(_Alloc& __a) noexcept { return __a; }
693f4ceed9Smrg    };
7048fb7bfaSmrg
7148fb7bfaSmrg  template<typename _Alloc>
723f4ceed9Smrg    struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>>
733f4ceed9Smrg    : __outermost_type<
743f4ceed9Smrg      typename remove_reference<__outer_allocator_t<_Alloc>>::type
753f4ceed9Smrg    >
763f4ceed9Smrg    {
773f4ceed9Smrg      using __base = __outermost_type<
783f4ceed9Smrg        typename remove_reference<__outer_allocator_t<_Alloc>>::type
793f4ceed9Smrg      >;
803f4ceed9Smrg
813f4ceed9Smrg      static typename __base::type&
82*0a307195Smrg      _S_outermost(_Alloc& __a) noexcept
833f4ceed9Smrg      { return __base::_S_outermost(__a.outer_allocator()); }
843f4ceed9Smrg    };
8548fb7bfaSmrg
86b1e83836Smrg  // Implementation of the OUTERMOST pseudofunction
8748fb7bfaSmrg  template<typename _Alloc>
883f4ceed9Smrg    inline typename __outermost_type<_Alloc>::type&
893f4ceed9Smrg    __outermost(_Alloc& __a)
903f4ceed9Smrg    { return __outermost_type<_Alloc>::_S_outermost(__a); }
9148fb7bfaSmrg
9248fb7bfaSmrg  template<typename...>
9348fb7bfaSmrg    struct __inner_type_impl;
9448fb7bfaSmrg
9548fb7bfaSmrg  template<typename _Outer>
9648fb7bfaSmrg    struct __inner_type_impl<_Outer>
9748fb7bfaSmrg    {
9848fb7bfaSmrg      typedef scoped_allocator_adaptor<_Outer> __type;
9948fb7bfaSmrg
10048fb7bfaSmrg      __inner_type_impl() = default;
10148fb7bfaSmrg      __inner_type_impl(const __inner_type_impl&) = default;
10248fb7bfaSmrg      __inner_type_impl(__inner_type_impl&&) = default;
1037e9e220aSmrg      __inner_type_impl& operator=(const __inner_type_impl&) = default;
1047e9e220aSmrg      __inner_type_impl& operator=(__inner_type_impl&&) = default;
10548fb7bfaSmrg
10648fb7bfaSmrg      template<typename _Alloc>
107*0a307195Smrg      __inner_type_impl(const __inner_type_impl<_Alloc>& __other) noexcept
10848fb7bfaSmrg      { }
10948fb7bfaSmrg
11048fb7bfaSmrg      template<typename _Alloc>
111*0a307195Smrg      __inner_type_impl(__inner_type_impl<_Alloc>&& __other) noexcept
11248fb7bfaSmrg      { }
11348fb7bfaSmrg
11448fb7bfaSmrg      __type&
11548fb7bfaSmrg      _M_get(__type* __p) noexcept { return *__p; }
11648fb7bfaSmrg
11748fb7bfaSmrg      const __type&
11848fb7bfaSmrg      _M_get(const __type* __p) const noexcept { return *__p; }
11948fb7bfaSmrg
12048fb7bfaSmrg      tuple<>
12148fb7bfaSmrg      _M_tie() const noexcept { return tuple<>(); }
12248fb7bfaSmrg
12348fb7bfaSmrg      bool
12448fb7bfaSmrg      operator==(const __inner_type_impl&) const noexcept
12548fb7bfaSmrg      { return true; }
12648fb7bfaSmrg    };
12748fb7bfaSmrg
12848fb7bfaSmrg  template<typename _Outer, typename _InnerHead, typename... _InnerTail>
12948fb7bfaSmrg    struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...>
13048fb7bfaSmrg    {
13148fb7bfaSmrg      typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type;
13248fb7bfaSmrg
13348fb7bfaSmrg      __inner_type_impl() = default;
13448fb7bfaSmrg      __inner_type_impl(const __inner_type_impl&) = default;
13548fb7bfaSmrg      __inner_type_impl(__inner_type_impl&&) = default;
1367e9e220aSmrg      __inner_type_impl& operator=(const __inner_type_impl&) = default;
1377e9e220aSmrg      __inner_type_impl& operator=(__inner_type_impl&&) = default;
13848fb7bfaSmrg
13948fb7bfaSmrg      template<typename... _Allocs>
140*0a307195Smrg      __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) noexcept
14148fb7bfaSmrg      : _M_inner(__other._M_inner) { }
14248fb7bfaSmrg
14348fb7bfaSmrg      template<typename... _Allocs>
144*0a307195Smrg      __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) noexcept
14548fb7bfaSmrg      : _M_inner(std::move(__other._M_inner)) { }
14648fb7bfaSmrg
14748fb7bfaSmrg    template<typename... _Args>
14848fb7bfaSmrg      explicit
149*0a307195Smrg      __inner_type_impl(_Args&&... __args) noexcept
15048fb7bfaSmrg      : _M_inner(std::forward<_Args>(__args)...) { }
15148fb7bfaSmrg
15248fb7bfaSmrg      __type&
15348fb7bfaSmrg      _M_get(void*) noexcept { return _M_inner; }
15448fb7bfaSmrg
15548fb7bfaSmrg      const __type&
15648fb7bfaSmrg      _M_get(const void*) const noexcept { return _M_inner; }
15748fb7bfaSmrg
15848fb7bfaSmrg      tuple<const _InnerHead&, const _InnerTail&...>
15948fb7bfaSmrg      _M_tie() const noexcept
16048fb7bfaSmrg      { return _M_inner._M_tie(); }
16148fb7bfaSmrg
16248fb7bfaSmrg      bool
16348fb7bfaSmrg      operator==(const __inner_type_impl& __other) const noexcept
16448fb7bfaSmrg      { return _M_inner == __other._M_inner; }
16548fb7bfaSmrg
16648fb7bfaSmrg    private:
167*0a307195Smrg      template<typename...> friend struct __inner_type_impl;
16848fb7bfaSmrg      template<typename, typename...> friend class scoped_allocator_adaptor;
16948fb7bfaSmrg
17048fb7bfaSmrg      __type _M_inner;
17148fb7bfaSmrg    };
17248fb7bfaSmrg
173fb8a8121Smrg  /// @endcond
174fb8a8121Smrg
175fb8a8121Smrg  /// An adaptor to recursively pass an allocator to the objects it constructs
17648fb7bfaSmrg  template<typename _OuterAlloc, typename... _InnerAllocs>
17748fb7bfaSmrg    class scoped_allocator_adaptor
17848fb7bfaSmrg    : public _OuterAlloc
17948fb7bfaSmrg    {
18048fb7bfaSmrg      typedef allocator_traits<_OuterAlloc> __traits;
18148fb7bfaSmrg
18248fb7bfaSmrg      typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type;
18348fb7bfaSmrg      __inner_type _M_inner;
18448fb7bfaSmrg
18548fb7bfaSmrg      template<typename _Outer, typename... _Inner>
18648fb7bfaSmrg        friend class scoped_allocator_adaptor;
18748fb7bfaSmrg
18848fb7bfaSmrg      template<typename...>
189*0a307195Smrg	friend struct __inner_type_impl;
19048fb7bfaSmrg
19148fb7bfaSmrg      tuple<const _OuterAlloc&, const _InnerAllocs&...>
19248fb7bfaSmrg      _M_tie() const noexcept
19348fb7bfaSmrg      { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); }
19448fb7bfaSmrg
19548fb7bfaSmrg      template<typename _Alloc>
19648fb7bfaSmrg	using __outermost_alloc_traits
1973f4ceed9Smrg	  = allocator_traits<typename __outermost_type<_Alloc>::type>;
19848fb7bfaSmrg
199b1e83836Smrg#if ! __cpp_lib_make_obj_using_allocator
20048fb7bfaSmrg      template<typename _Tp, typename... _Args>
20148fb7bfaSmrg        void
20248fb7bfaSmrg        _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args)
20348fb7bfaSmrg        {
20448fb7bfaSmrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
20548fb7bfaSmrg	  _O_traits::construct(__outermost(*this), __p,
20648fb7bfaSmrg			       std::forward<_Args>(__args)...);
20748fb7bfaSmrg        }
20848fb7bfaSmrg
20948fb7bfaSmrg      typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_;
21048fb7bfaSmrg      typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_;
21148fb7bfaSmrg
21248fb7bfaSmrg      template<typename _Tp, typename... _Args>
21348fb7bfaSmrg        void
21448fb7bfaSmrg        _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args)
21548fb7bfaSmrg        {
21648fb7bfaSmrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
21748fb7bfaSmrg	  _O_traits::construct(__outermost(*this), __p,
21848fb7bfaSmrg			       allocator_arg, inner_allocator(),
21948fb7bfaSmrg			       std::forward<_Args>(__args)...);
22048fb7bfaSmrg        }
22148fb7bfaSmrg
22248fb7bfaSmrg      template<typename _Tp, typename... _Args>
22348fb7bfaSmrg        void
22448fb7bfaSmrg        _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args)
22548fb7bfaSmrg        {
22648fb7bfaSmrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
22748fb7bfaSmrg	  _O_traits::construct(__outermost(*this), __p,
22848fb7bfaSmrg			       std::forward<_Args>(__args)...,
22948fb7bfaSmrg			       inner_allocator());
23048fb7bfaSmrg        }
231b1e83836Smrg#endif // ! make_obj_using_allocator
23248fb7bfaSmrg
23348fb7bfaSmrg      template<typename _Alloc>
23448fb7bfaSmrg        static _Alloc
23548fb7bfaSmrg        _S_select_on_copy(const _Alloc& __a)
23648fb7bfaSmrg        {
23748fb7bfaSmrg          typedef allocator_traits<_Alloc> __a_traits;
23848fb7bfaSmrg          return __a_traits::select_on_container_copy_construction(__a);
23948fb7bfaSmrg        }
24048fb7bfaSmrg
24148fb7bfaSmrg      template<std::size_t... _Indices>
24248fb7bfaSmrg        scoped_allocator_adaptor(tuple<const _OuterAlloc&,
24348fb7bfaSmrg                                       const _InnerAllocs&...> __refs,
24448fb7bfaSmrg                                 _Index_tuple<_Indices...>)
24548fb7bfaSmrg        : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))),
24648fb7bfaSmrg          _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...)
24748fb7bfaSmrg        { }
24848fb7bfaSmrg
2493f4ceed9Smrg      // Used to constrain constructors to disallow invalid conversions.
2503f4ceed9Smrg      template<typename _Alloc>
2513f4ceed9Smrg        using _Constructible = typename enable_if<
2523f4ceed9Smrg            is_constructible<_OuterAlloc, _Alloc>::value
2533f4ceed9Smrg          >::type;
2543f4ceed9Smrg
255181254a7Smrg      // _GLIBCXX_RESOLVE_LIB_DEFECTS
256181254a7Smrg      // 2975. Missing case for pair construction in scoped [...] allocators
257181254a7Smrg      template<typename _Tp>
258181254a7Smrg	struct __not_pair { using type = void; };
259181254a7Smrg
260181254a7Smrg      template<typename _Tp, typename _Up>
261181254a7Smrg	struct __not_pair<pair<_Tp, _Up>> { };
262181254a7Smrg
26348fb7bfaSmrg    public:
26448fb7bfaSmrg      typedef _OuterAlloc                       outer_allocator_type;
26548fb7bfaSmrg      typedef typename __inner_type::__type     inner_allocator_type;
26648fb7bfaSmrg
26748fb7bfaSmrg      typedef typename __traits::value_type             value_type;
26848fb7bfaSmrg      typedef typename __traits::size_type              size_type;
26948fb7bfaSmrg      typedef typename __traits::difference_type        difference_type;
27048fb7bfaSmrg      typedef typename __traits::pointer                pointer;
27148fb7bfaSmrg      typedef typename __traits::const_pointer          const_pointer;
27248fb7bfaSmrg      typedef typename __traits::void_pointer           void_pointer;
27348fb7bfaSmrg      typedef typename __traits::const_void_pointer     const_void_pointer;
27448fb7bfaSmrg
275f9a78e0eSmrg      typedef typename __or_<
276f9a78e0eSmrg	typename __traits::propagate_on_container_copy_assignment,
277f9a78e0eSmrg	typename allocator_traits<_InnerAllocs>::
278f9a78e0eSmrg	  propagate_on_container_copy_assignment...>::type
279f9a78e0eSmrg	  propagate_on_container_copy_assignment;
280f9a78e0eSmrg
281f9a78e0eSmrg      typedef typename __or_<
282f9a78e0eSmrg	typename __traits::propagate_on_container_move_assignment,
283f9a78e0eSmrg	typename allocator_traits<_InnerAllocs>::
284f9a78e0eSmrg	  propagate_on_container_move_assignment...>::type
285f9a78e0eSmrg	  propagate_on_container_move_assignment;
286f9a78e0eSmrg
287f9a78e0eSmrg      typedef typename __or_<
288f9a78e0eSmrg	typename __traits::propagate_on_container_swap,
289f9a78e0eSmrg	typename allocator_traits<_InnerAllocs>::
290f9a78e0eSmrg	  propagate_on_container_swap...>::type
291f9a78e0eSmrg	  propagate_on_container_swap;
292f9a78e0eSmrg
293f9a78e0eSmrg      typedef typename __and_<
294f9a78e0eSmrg	typename __traits::is_always_equal,
295f9a78e0eSmrg	typename allocator_traits<_InnerAllocs>::is_always_equal...>::type
296f9a78e0eSmrg	  is_always_equal;
29748fb7bfaSmrg
29848fb7bfaSmrg      template <class _Tp>
29948fb7bfaSmrg        struct rebind
30048fb7bfaSmrg        {
30148fb7bfaSmrg          typedef scoped_allocator_adaptor<
30248fb7bfaSmrg            typename __traits::template rebind_alloc<_Tp>,
30348fb7bfaSmrg            _InnerAllocs...> other;
30448fb7bfaSmrg        };
30548fb7bfaSmrg
30648fb7bfaSmrg      scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
30748fb7bfaSmrg
3083f4ceed9Smrg      template<typename _Outer2, typename = _Constructible<_Outer2>>
30948fb7bfaSmrg        scoped_allocator_adaptor(_Outer2&& __outer,
310*0a307195Smrg                                 const _InnerAllocs&... __inner) noexcept
31148fb7bfaSmrg        : _OuterAlloc(std::forward<_Outer2>(__outer)),
31248fb7bfaSmrg          _M_inner(__inner...)
31348fb7bfaSmrg        { }
31448fb7bfaSmrg
315*0a307195Smrg      scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) noexcept
31648fb7bfaSmrg      : _OuterAlloc(__other.outer_allocator()),
31748fb7bfaSmrg	_M_inner(__other._M_inner)
31848fb7bfaSmrg      { }
31948fb7bfaSmrg
320*0a307195Smrg      scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) noexcept
32148fb7bfaSmrg      : _OuterAlloc(std::move(__other.outer_allocator())),
32248fb7bfaSmrg	_M_inner(std::move(__other._M_inner))
32348fb7bfaSmrg      { }
32448fb7bfaSmrg
3253f4ceed9Smrg      template<typename _Outer2, typename = _Constructible<const _Outer2&>>
32648fb7bfaSmrg        scoped_allocator_adaptor(
327*0a307195Smrg	  const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other
328*0a307195Smrg	) noexcept
32948fb7bfaSmrg        : _OuterAlloc(__other.outer_allocator()),
33048fb7bfaSmrg          _M_inner(__other._M_inner)
33148fb7bfaSmrg        { }
33248fb7bfaSmrg
3333f4ceed9Smrg      template<typename _Outer2, typename = _Constructible<_Outer2>>
33448fb7bfaSmrg        scoped_allocator_adaptor(
335*0a307195Smrg	  scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) noexcept
33648fb7bfaSmrg        : _OuterAlloc(std::move(__other.outer_allocator())),
33748fb7bfaSmrg          _M_inner(std::move(__other._M_inner))
33848fb7bfaSmrg        { }
33948fb7bfaSmrg
3407e9e220aSmrg      scoped_allocator_adaptor&
3417e9e220aSmrg      operator=(const scoped_allocator_adaptor&) = default;
3427e9e220aSmrg
3437e9e220aSmrg      scoped_allocator_adaptor&
3447e9e220aSmrg      operator=(scoped_allocator_adaptor&&) = default;
3457e9e220aSmrg
346*0a307195Smrg      inner_allocator_type&
347*0a307195Smrg      inner_allocator() noexcept
34848fb7bfaSmrg      { return _M_inner._M_get(this); }
34948fb7bfaSmrg
350*0a307195Smrg      const inner_allocator_type&
351*0a307195Smrg      inner_allocator() const noexcept
35248fb7bfaSmrg      { return _M_inner._M_get(this); }
35348fb7bfaSmrg
354*0a307195Smrg      outer_allocator_type&
355*0a307195Smrg      outer_allocator() noexcept
35648fb7bfaSmrg      { return static_cast<_OuterAlloc&>(*this); }
35748fb7bfaSmrg
358*0a307195Smrg      const outer_allocator_type&
359*0a307195Smrg      outer_allocator() const noexcept
36048fb7bfaSmrg      { return static_cast<const _OuterAlloc&>(*this); }
36148fb7bfaSmrg
362*0a307195Smrg      _GLIBCXX_NODISCARD pointer
363*0a307195Smrg      allocate(size_type __n)
36448fb7bfaSmrg      { return __traits::allocate(outer_allocator(), __n); }
36548fb7bfaSmrg
366*0a307195Smrg      _GLIBCXX_NODISCARD pointer
367*0a307195Smrg      allocate(size_type __n, const_void_pointer __hint)
36848fb7bfaSmrg      { return __traits::allocate(outer_allocator(), __n, __hint); }
36948fb7bfaSmrg
370*0a307195Smrg      void deallocate(pointer __p, size_type __n) noexcept
37148fb7bfaSmrg      { return __traits::deallocate(outer_allocator(), __p, __n); }
37248fb7bfaSmrg
37348fb7bfaSmrg      size_type max_size() const
37448fb7bfaSmrg      { return __traits::max_size(outer_allocator()); }
37548fb7bfaSmrg
376b1e83836Smrg#if ! __cpp_lib_make_obj_using_allocator
37748fb7bfaSmrg      template<typename _Tp, typename... _Args>
378181254a7Smrg	typename __not_pair<_Tp>::type
379181254a7Smrg	construct(_Tp* __p, _Args&&... __args)
38048fb7bfaSmrg	{
38148fb7bfaSmrg	  auto& __inner = inner_allocator();
38248fb7bfaSmrg	  auto __use_tag
383181254a7Smrg	    = std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
38448fb7bfaSmrg	  _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
38548fb7bfaSmrg	}
38648fb7bfaSmrg
38748fb7bfaSmrg      template<typename _T1, typename _T2, typename... _Args1,
38848fb7bfaSmrg	       typename... _Args2>
38948fb7bfaSmrg	void
39048fb7bfaSmrg	construct(pair<_T1, _T2>* __p, piecewise_construct_t,
39148fb7bfaSmrg		  tuple<_Args1...> __x, tuple<_Args2...> __y)
39248fb7bfaSmrg	{
39348fb7bfaSmrg	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
39448fb7bfaSmrg	  // 2203.  wrong argument types for piecewise construction
39548fb7bfaSmrg	  auto& __inner = inner_allocator();
39648fb7bfaSmrg	  auto __x_use_tag
397181254a7Smrg	    = std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner);
39848fb7bfaSmrg	  auto __y_use_tag
399181254a7Smrg	    = std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner);
400b17d1066Smrg	  typename _Build_index_tuple<sizeof...(_Args1)>::__type __x_indices;
401b17d1066Smrg	  typename _Build_index_tuple<sizeof...(_Args2)>::__type __y_indices;
40248fb7bfaSmrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
40348fb7bfaSmrg	  _O_traits::construct(__outermost(*this), __p, piecewise_construct,
404b17d1066Smrg			       _M_construct_p(__x_use_tag, __x_indices, __x),
405b17d1066Smrg			       _M_construct_p(__y_use_tag, __y_indices, __y));
40648fb7bfaSmrg	}
40748fb7bfaSmrg
40848fb7bfaSmrg      template<typename _T1, typename _T2>
40948fb7bfaSmrg	void
41048fb7bfaSmrg	construct(pair<_T1, _T2>* __p)
41148fb7bfaSmrg	{ construct(__p, piecewise_construct, tuple<>(), tuple<>()); }
41248fb7bfaSmrg
41348fb7bfaSmrg      template<typename _T1, typename _T2, typename _Up, typename _Vp>
41448fb7bfaSmrg	void
41548fb7bfaSmrg	construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v)
41648fb7bfaSmrg	{
41748fb7bfaSmrg	  construct(__p, piecewise_construct,
41848fb7bfaSmrg		    std::forward_as_tuple(std::forward<_Up>(__u)),
41948fb7bfaSmrg		    std::forward_as_tuple(std::forward<_Vp>(__v)));
42048fb7bfaSmrg	}
42148fb7bfaSmrg
42248fb7bfaSmrg      template<typename _T1, typename _T2, typename _Up, typename _Vp>
42348fb7bfaSmrg	void
42448fb7bfaSmrg	construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x)
42548fb7bfaSmrg	{
42648fb7bfaSmrg	  construct(__p, piecewise_construct,
42748fb7bfaSmrg		    std::forward_as_tuple(__x.first),
42848fb7bfaSmrg		    std::forward_as_tuple(__x.second));
42948fb7bfaSmrg	}
43048fb7bfaSmrg
43148fb7bfaSmrg      template<typename _T1, typename _T2, typename _Up, typename _Vp>
43248fb7bfaSmrg	void
43348fb7bfaSmrg	construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x)
43448fb7bfaSmrg	{
43548fb7bfaSmrg	  construct(__p, piecewise_construct,
43648fb7bfaSmrg		    std::forward_as_tuple(std::forward<_Up>(__x.first)),
43748fb7bfaSmrg		    std::forward_as_tuple(std::forward<_Vp>(__x.second)));
43848fb7bfaSmrg	}
439b1e83836Smrg#else // make_obj_using_allocator
440181254a7Smrg      template<typename _Tp, typename... _Args>
441181254a7Smrg	__attribute__((__nonnull__))
442181254a7Smrg	void
443181254a7Smrg	construct(_Tp* __p, _Args&&... __args)
444181254a7Smrg	{
445181254a7Smrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
446181254a7Smrg	  std::apply([__p, this](auto&&... __newargs) {
447181254a7Smrg	      _O_traits::construct(__outermost(*this), __p,
448181254a7Smrg		  std::forward<decltype(__newargs)>(__newargs)...);
449181254a7Smrg	  },
450181254a7Smrg	  uses_allocator_construction_args<_Tp>(inner_allocator(),
451181254a7Smrg	    std::forward<_Args>(__args)...));
452181254a7Smrg	}
453b1e83836Smrg#endif
45448fb7bfaSmrg
45548fb7bfaSmrg      template<typename _Tp>
45648fb7bfaSmrg        void destroy(_Tp* __p)
45748fb7bfaSmrg        {
45848fb7bfaSmrg	  typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
45948fb7bfaSmrg	  _O_traits::destroy(__outermost(*this), __p);
46048fb7bfaSmrg	}
46148fb7bfaSmrg
46248fb7bfaSmrg      scoped_allocator_adaptor
46348fb7bfaSmrg      select_on_container_copy_construction() const
46448fb7bfaSmrg      {
46548fb7bfaSmrg        typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type
46648fb7bfaSmrg	    _Indices;
46748fb7bfaSmrg        return scoped_allocator_adaptor(_M_tie(), _Indices());
46848fb7bfaSmrg      }
46948fb7bfaSmrg
47048fb7bfaSmrg      template <typename _OutA1, typename _OutA2, typename... _InA>
47148fb7bfaSmrg      friend bool
47248fb7bfaSmrg      operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
47348fb7bfaSmrg                 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept;
47448fb7bfaSmrg
47548fb7bfaSmrg    private:
476b1e83836Smrg#if ! __cpp_lib_make_obj_using_allocator
477b17d1066Smrg      template<typename _Ind, typename... _Args>
478b17d1066Smrg	tuple<_Args&&...>
479b17d1066Smrg	_M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t)
48048fb7bfaSmrg	{ return std::move(__t); }
48148fb7bfaSmrg
482b17d1066Smrg      template<size_t... _Ind, typename... _Args>
483b17d1066Smrg	tuple<allocator_arg_t, inner_allocator_type&, _Args&&...>
484b17d1066Smrg	_M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>,
485b17d1066Smrg		       tuple<_Args...>& __t)
48648fb7bfaSmrg	{
487b17d1066Smrg	  return { allocator_arg, inner_allocator(),
488b17d1066Smrg	      std::get<_Ind>(std::move(__t))...
489b17d1066Smrg	  };
49048fb7bfaSmrg	}
49148fb7bfaSmrg
492b17d1066Smrg      template<size_t... _Ind, typename... _Args>
493b17d1066Smrg	tuple<_Args&&..., inner_allocator_type&>
494b17d1066Smrg	_M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>,
495b17d1066Smrg		       tuple<_Args...>& __t)
49648fb7bfaSmrg	{
497b17d1066Smrg	  return { std::get<_Ind>(std::move(__t))..., inner_allocator() };
49848fb7bfaSmrg	}
499b1e83836Smrg#endif // ! make_obj_using_allocator
50048fb7bfaSmrg    };
50148fb7bfaSmrg
502fb8a8121Smrg  /// @related std::scoped_allocator_adaptor
50348fb7bfaSmrg  template <typename _OutA1, typename _OutA2, typename... _InA>
50448fb7bfaSmrg    inline bool
50548fb7bfaSmrg    operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
50648fb7bfaSmrg               const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
50748fb7bfaSmrg    {
50848fb7bfaSmrg      return __a.outer_allocator() == __b.outer_allocator()
50948fb7bfaSmrg          && __a._M_inner == __b._M_inner;
51048fb7bfaSmrg    }
51148fb7bfaSmrg
512fb8a8121Smrg#if __cpp_impl_three_way_comparison < 201907L
513fb8a8121Smrg  /// @related std::scoped_allocator_adaptor
51448fb7bfaSmrg  template <typename _OutA1, typename _OutA2, typename... _InA>
51548fb7bfaSmrg    inline bool
51648fb7bfaSmrg    operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
51748fb7bfaSmrg               const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
51848fb7bfaSmrg    { return !(__a == __b); }
519fb8a8121Smrg#endif
52048fb7bfaSmrg
52148fb7bfaSmrg  /// @}
52248fb7bfaSmrg
52348fb7bfaSmrg_GLIBCXX_END_NAMESPACE_VERSION
52448fb7bfaSmrg} // namespace
52548fb7bfaSmrg
52648fb7bfaSmrg#endif // C++11
52748fb7bfaSmrg
52848fb7bfaSmrg#endif // _SCOPED_ALLOCATOR
529