xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/alloc_traits.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
148fb7bfaSmrg // Allocator traits -*- 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 bits/alloc_traits.h
2648fb7bfaSmrg  *  This is an internal header file, included by other library headers.
2748fb7bfaSmrg  *  Do not attempt to use it directly. @headername{memory}
2848fb7bfaSmrg  */
2948fb7bfaSmrg 
3048fb7bfaSmrg #ifndef _ALLOC_TRAITS_H
3148fb7bfaSmrg #define _ALLOC_TRAITS_H 1
3248fb7bfaSmrg 
33fb8a8121Smrg #include <bits/stl_construct.h>
3448fb7bfaSmrg #include <bits/memoryfwd.h>
35fb8a8121Smrg #if __cplusplus >= 201103L
36fb8a8121Smrg # include <bits/allocator.h>
3748fb7bfaSmrg # include <bits/ptr_traits.h>
3848fb7bfaSmrg # include <ext/numeric_traits.h>
39fb8a8121Smrg #endif
40f9a78e0eSmrg 
_GLIBCXX_VISIBILITY(default)4148fb7bfaSmrg namespace std _GLIBCXX_VISIBILITY(default)
4248fb7bfaSmrg {
4348fb7bfaSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
4448fb7bfaSmrg 
45fb8a8121Smrg #if __cplusplus >= 201103L
46b1e83836Smrg #define __cpp_lib_allocator_traits_is_always_equal 201411L
47fb8a8121Smrg 
48b1e83836Smrg   /// @cond undocumented
49f9a78e0eSmrg   struct __allocator_traits_base
5048fb7bfaSmrg   {
51f9a78e0eSmrg     template<typename _Tp, typename _Up, typename = void>
52f9a78e0eSmrg       struct __rebind : __replace_first_arg<_Tp, _Up> { };
5348fb7bfaSmrg 
54f9a78e0eSmrg     template<typename _Tp, typename _Up>
55f9a78e0eSmrg       struct __rebind<_Tp, _Up,
56f9a78e0eSmrg 		      __void_t<typename _Tp::template rebind<_Up>::other>>
57f9a78e0eSmrg       { using type = typename _Tp::template rebind<_Up>::other; };
5848fb7bfaSmrg 
59f9a78e0eSmrg   protected:
60f9a78e0eSmrg     template<typename _Tp>
61f9a78e0eSmrg       using __pointer = typename _Tp::pointer;
62f9a78e0eSmrg     template<typename _Tp>
63f9a78e0eSmrg       using __c_pointer = typename _Tp::const_pointer;
64f9a78e0eSmrg     template<typename _Tp>
65f9a78e0eSmrg       using __v_pointer = typename _Tp::void_pointer;
66f9a78e0eSmrg     template<typename _Tp>
67f9a78e0eSmrg       using __cv_pointer = typename _Tp::const_void_pointer;
68f9a78e0eSmrg     template<typename _Tp>
69f9a78e0eSmrg       using __pocca = typename _Tp::propagate_on_container_copy_assignment;
70f9a78e0eSmrg     template<typename _Tp>
71f9a78e0eSmrg       using __pocma = typename _Tp::propagate_on_container_move_assignment;
72f9a78e0eSmrg     template<typename _Tp>
73f9a78e0eSmrg       using __pocs = typename _Tp::propagate_on_container_swap;
74f9a78e0eSmrg     template<typename _Tp>
75*0a307195Smrg       using __equal = __type_identity<typename _Tp::is_always_equal>;
7648fb7bfaSmrg   };
7748fb7bfaSmrg 
78f9a78e0eSmrg   template<typename _Alloc, typename _Up>
79f9a78e0eSmrg     using __alloc_rebind
80f9a78e0eSmrg       = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
81b1e83836Smrg   /// @endcond
824d5abbe8Smrg 
8348fb7bfaSmrg   /**
8448fb7bfaSmrg    * @brief  Uniform interface to all allocator types.
85b1e83836Smrg    * @headerfile memory
8648fb7bfaSmrg    * @ingroup allocators
87b1e83836Smrg    * @since C++11
8848fb7bfaSmrg   */
8948fb7bfaSmrg   template<typename _Alloc>
90f9a78e0eSmrg     struct allocator_traits : __allocator_traits_base
9148fb7bfaSmrg     {
9248fb7bfaSmrg       /// The allocator type
9348fb7bfaSmrg       typedef _Alloc allocator_type;
9448fb7bfaSmrg       /// The allocated type
9548fb7bfaSmrg       typedef typename _Alloc::value_type value_type;
9648fb7bfaSmrg 
9748fb7bfaSmrg       /**
9848fb7bfaSmrg        * @brief   The allocator's pointer type.
9948fb7bfaSmrg        *
10048fb7bfaSmrg        * @c Alloc::pointer if that type exists, otherwise @c value_type*
10148fb7bfaSmrg       */
102f9a78e0eSmrg       using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
10348fb7bfaSmrg 
104f9a78e0eSmrg     private:
105f9a78e0eSmrg       // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
106f9a78e0eSmrg       template<template<typename> class _Func, typename _Tp, typename = void>
107f9a78e0eSmrg 	struct _Ptr
108f9a78e0eSmrg 	{
109f9a78e0eSmrg 	  using type = typename pointer_traits<pointer>::template rebind<_Tp>;
110f9a78e0eSmrg 	};
11148fb7bfaSmrg 
112f9a78e0eSmrg       template<template<typename> class _Func, typename _Tp>
113f9a78e0eSmrg 	struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
114f9a78e0eSmrg 	{
115f9a78e0eSmrg 	  using type = _Func<_Alloc>;
116f9a78e0eSmrg 	};
117f9a78e0eSmrg 
118f9a78e0eSmrg       // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
119f9a78e0eSmrg       template<typename _A2, typename _PtrT, typename = void>
120f9a78e0eSmrg 	struct _Diff
121f9a78e0eSmrg 	{ using type = typename pointer_traits<_PtrT>::difference_type; };
122f9a78e0eSmrg 
123f9a78e0eSmrg       template<typename _A2, typename _PtrT>
124f9a78e0eSmrg 	struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
125f9a78e0eSmrg 	{ using type = typename _A2::difference_type; };
126f9a78e0eSmrg 
127f9a78e0eSmrg       // Select _A2::size_type or make_unsigned<_DiffT>::type
128f9a78e0eSmrg       template<typename _A2, typename _DiffT, typename = void>
129f9a78e0eSmrg 	struct _Size : make_unsigned<_DiffT> { };
130f9a78e0eSmrg 
131f9a78e0eSmrg       template<typename _A2, typename _DiffT>
132f9a78e0eSmrg 	struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
133f9a78e0eSmrg 	{ using type = typename _A2::size_type; };
134f9a78e0eSmrg 
135f9a78e0eSmrg     public:
13648fb7bfaSmrg       /**
13748fb7bfaSmrg        * @brief   The allocator's const pointer type.
13848fb7bfaSmrg        *
13948fb7bfaSmrg        * @c Alloc::const_pointer if that type exists, otherwise
14048fb7bfaSmrg        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
14148fb7bfaSmrg       */
142f9a78e0eSmrg       using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
14348fb7bfaSmrg 
14448fb7bfaSmrg       /**
14548fb7bfaSmrg        * @brief   The allocator's void pointer type.
14648fb7bfaSmrg        *
14748fb7bfaSmrg        * @c Alloc::void_pointer if that type exists, otherwise
14848fb7bfaSmrg        * <tt> pointer_traits<pointer>::rebind<void> </tt>
14948fb7bfaSmrg       */
150f9a78e0eSmrg       using void_pointer = typename _Ptr<__v_pointer, void>::type;
15148fb7bfaSmrg 
15248fb7bfaSmrg       /**
15348fb7bfaSmrg        * @brief   The allocator's const void pointer type.
15448fb7bfaSmrg        *
15548fb7bfaSmrg        * @c Alloc::const_void_pointer if that type exists, otherwise
15648fb7bfaSmrg        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
15748fb7bfaSmrg       */
158f9a78e0eSmrg       using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
15948fb7bfaSmrg 
16048fb7bfaSmrg       /**
16148fb7bfaSmrg        * @brief   The allocator's difference type
16248fb7bfaSmrg        *
16348fb7bfaSmrg        * @c Alloc::difference_type if that type exists, otherwise
16448fb7bfaSmrg        * <tt> pointer_traits<pointer>::difference_type </tt>
16548fb7bfaSmrg       */
166f9a78e0eSmrg       using difference_type = typename _Diff<_Alloc, pointer>::type;
16748fb7bfaSmrg 
16848fb7bfaSmrg       /**
16948fb7bfaSmrg        * @brief   The allocator's size type
17048fb7bfaSmrg        *
17148fb7bfaSmrg        * @c Alloc::size_type if that type exists, otherwise
17248fb7bfaSmrg        * <tt> make_unsigned<difference_type>::type </tt>
17348fb7bfaSmrg       */
174f9a78e0eSmrg       using size_type = typename _Size<_Alloc, difference_type>::type;
17548fb7bfaSmrg 
17648fb7bfaSmrg       /**
17748fb7bfaSmrg        * @brief   How the allocator is propagated on copy assignment
17848fb7bfaSmrg        *
17948fb7bfaSmrg        * @c Alloc::propagate_on_container_copy_assignment if that type exists,
18048fb7bfaSmrg        * otherwise @c false_type
18148fb7bfaSmrg       */
182f9a78e0eSmrg       using propagate_on_container_copy_assignment
183f9a78e0eSmrg 	= __detected_or_t<false_type, __pocca, _Alloc>;
18448fb7bfaSmrg 
18548fb7bfaSmrg       /**
18648fb7bfaSmrg        * @brief   How the allocator is propagated on move assignment
18748fb7bfaSmrg        *
18848fb7bfaSmrg        * @c Alloc::propagate_on_container_move_assignment if that type exists,
18948fb7bfaSmrg        * otherwise @c false_type
19048fb7bfaSmrg       */
191f9a78e0eSmrg       using propagate_on_container_move_assignment
192f9a78e0eSmrg 	= __detected_or_t<false_type, __pocma, _Alloc>;
19348fb7bfaSmrg 
19448fb7bfaSmrg       /**
19548fb7bfaSmrg        * @brief   How the allocator is propagated on swap
19648fb7bfaSmrg        *
19748fb7bfaSmrg        * @c Alloc::propagate_on_container_swap if that type exists,
19848fb7bfaSmrg        * otherwise @c false_type
19948fb7bfaSmrg       */
200f9a78e0eSmrg       using propagate_on_container_swap
201f9a78e0eSmrg 	= __detected_or_t<false_type, __pocs, _Alloc>;
20248fb7bfaSmrg 
203f9a78e0eSmrg       /**
204f9a78e0eSmrg        * @brief   Whether all instances of the allocator type compare equal.
205f9a78e0eSmrg        *
206f9a78e0eSmrg        * @c Alloc::is_always_equal if that type exists,
207f9a78e0eSmrg        * otherwise @c is_empty<Alloc>::type
208f9a78e0eSmrg       */
209f9a78e0eSmrg       using is_always_equal
210*0a307195Smrg 	= typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
21148fb7bfaSmrg 
21248fb7bfaSmrg       template<typename _Tp>
213f9a78e0eSmrg 	using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
21448fb7bfaSmrg       template<typename _Tp>
21548fb7bfaSmrg 	using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
21648fb7bfaSmrg 
21748fb7bfaSmrg     private:
21848fb7bfaSmrg       template<typename _Alloc2>
219fb8a8121Smrg 	static constexpr auto
220f9a78e0eSmrg 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
221f9a78e0eSmrg 	-> decltype(__a.allocate(__n, __hint))
22248fb7bfaSmrg 	{ return __a.allocate(__n, __hint); }
22348fb7bfaSmrg 
224f9a78e0eSmrg       template<typename _Alloc2>
225fb8a8121Smrg 	static constexpr pointer
226f9a78e0eSmrg 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
22748fb7bfaSmrg 	{ return __a.allocate(__n); }
22848fb7bfaSmrg 
22948fb7bfaSmrg       template<typename _Tp, typename... _Args>
23048fb7bfaSmrg 	struct __construct_helper
23148fb7bfaSmrg 	{
23248fb7bfaSmrg 	  template<typename _Alloc2,
23348fb7bfaSmrg 	    typename = decltype(std::declval<_Alloc2*>()->construct(
23448fb7bfaSmrg 		  std::declval<_Tp*>(), std::declval<_Args>()...))>
23548fb7bfaSmrg 	    static true_type __test(int);
23648fb7bfaSmrg 
23748fb7bfaSmrg 	  template<typename>
23848fb7bfaSmrg 	    static false_type __test(...);
23948fb7bfaSmrg 
2404d5abbe8Smrg 	  using type = decltype(__test<_Alloc>(0));
24148fb7bfaSmrg 	};
24248fb7bfaSmrg 
24348fb7bfaSmrg       template<typename _Tp, typename... _Args>
2444d5abbe8Smrg 	using __has_construct
2454d5abbe8Smrg 	  = typename __construct_helper<_Tp, _Args...>::type;
2464d5abbe8Smrg 
2474d5abbe8Smrg       template<typename _Tp, typename... _Args>
248fb8a8121Smrg 	static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>>
24948fb7bfaSmrg 	_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
250181254a7Smrg 	noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
25148fb7bfaSmrg 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
25248fb7bfaSmrg 
25348fb7bfaSmrg       template<typename _Tp, typename... _Args>
254fb8a8121Smrg 	static _GLIBCXX14_CONSTEXPR
2554d5abbe8Smrg 	_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
2564d5abbe8Smrg 			       is_constructible<_Tp, _Args...>>>
25748fb7bfaSmrg 	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
258fb8a8121Smrg 	noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
259fb8a8121Smrg 	{
260fb8a8121Smrg #if __cplusplus <= 201703L
261fb8a8121Smrg 	  ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
262fb8a8121Smrg #else
263fb8a8121Smrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
264fb8a8121Smrg #endif
265fb8a8121Smrg 	}
26648fb7bfaSmrg 
267f9a78e0eSmrg       template<typename _Alloc2, typename _Tp>
268fb8a8121Smrg 	static _GLIBCXX14_CONSTEXPR auto
269f9a78e0eSmrg 	_S_destroy(_Alloc2& __a, _Tp* __p, int)
270181254a7Smrg 	noexcept(noexcept(__a.destroy(__p)))
271f9a78e0eSmrg 	-> decltype(__a.destroy(__p))
27248fb7bfaSmrg 	{ __a.destroy(__p); }
27348fb7bfaSmrg 
274f9a78e0eSmrg       template<typename _Alloc2, typename _Tp>
275fb8a8121Smrg 	static _GLIBCXX14_CONSTEXPR void
276f9a78e0eSmrg 	_S_destroy(_Alloc2&, _Tp* __p, ...)
277fb8a8121Smrg 	noexcept(std::is_nothrow_destructible<_Tp>::value)
278fb8a8121Smrg 	{ std::_Destroy(__p); }
27948fb7bfaSmrg 
28048fb7bfaSmrg       template<typename _Alloc2>
281fb8a8121Smrg 	static constexpr auto
2824d5abbe8Smrg 	_S_max_size(_Alloc2& __a, int)
283f9a78e0eSmrg 	-> decltype(__a.max_size())
28448fb7bfaSmrg 	{ return __a.max_size(); }
28548fb7bfaSmrg 
286f9a78e0eSmrg       template<typename _Alloc2>
287fb8a8121Smrg 	static constexpr size_type
2884d5abbe8Smrg 	_S_max_size(_Alloc2&, ...)
28948fb7bfaSmrg 	{
290f9a78e0eSmrg 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
291f9a78e0eSmrg 	  // 2466. allocator_traits::max_size() default behavior is incorrect
292f9a78e0eSmrg 	  return __gnu_cxx::__numeric_traits<size_type>::__max
293f9a78e0eSmrg 	    / sizeof(value_type);
294f9a78e0eSmrg 	}
29548fb7bfaSmrg 
29648fb7bfaSmrg       template<typename _Alloc2>
297fb8a8121Smrg 	static constexpr auto
2984d5abbe8Smrg 	_S_select(_Alloc2& __a, int)
299f9a78e0eSmrg 	-> decltype(__a.select_on_container_copy_construction())
3004d5abbe8Smrg 	{ return __a.select_on_container_copy_construction(); }
3014d5abbe8Smrg 
302f9a78e0eSmrg       template<typename _Alloc2>
303fb8a8121Smrg 	static constexpr _Alloc2
3044d5abbe8Smrg 	_S_select(_Alloc2& __a, ...)
30548fb7bfaSmrg 	{ return __a; }
30648fb7bfaSmrg 
30748fb7bfaSmrg     public:
30848fb7bfaSmrg 
30948fb7bfaSmrg       /**
31048fb7bfaSmrg        *  @brief  Allocate memory.
31148fb7bfaSmrg        *  @param  __a  An allocator.
31248fb7bfaSmrg        *  @param  __n  The number of objects to allocate space for.
31348fb7bfaSmrg        *
31448fb7bfaSmrg        *  Calls @c a.allocate(n)
31548fb7bfaSmrg       */
316fb8a8121Smrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
31748fb7bfaSmrg       allocate(_Alloc& __a, size_type __n)
31848fb7bfaSmrg       { return __a.allocate(__n); }
31948fb7bfaSmrg 
32048fb7bfaSmrg       /**
32148fb7bfaSmrg        *  @brief  Allocate memory.
32248fb7bfaSmrg        *  @param  __a  An allocator.
32348fb7bfaSmrg        *  @param  __n  The number of objects to allocate space for.
32448fb7bfaSmrg        *  @param  __hint Aid to locality.
32548fb7bfaSmrg        *  @return Memory of suitable size and alignment for @a n objects
32648fb7bfaSmrg        *          of type @c value_type
32748fb7bfaSmrg        *
32848fb7bfaSmrg        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
32948fb7bfaSmrg        *  well-formed, otherwise returns @c a.allocate(n)
33048fb7bfaSmrg       */
331fb8a8121Smrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
33248fb7bfaSmrg       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
333f9a78e0eSmrg       { return _S_allocate(__a, __n, __hint, 0); }
33448fb7bfaSmrg 
33548fb7bfaSmrg       /**
33648fb7bfaSmrg        *  @brief  Deallocate memory.
33748fb7bfaSmrg        *  @param  __a  An allocator.
33848fb7bfaSmrg        *  @param  __p  Pointer to the memory to deallocate.
33948fb7bfaSmrg        *  @param  __n  The number of objects space was allocated for.
34048fb7bfaSmrg        *
34148fb7bfaSmrg        *  Calls <tt> a.deallocate(p, n) </tt>
34248fb7bfaSmrg       */
343fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR void
344f9a78e0eSmrg       deallocate(_Alloc& __a, pointer __p, size_type __n)
34548fb7bfaSmrg       { __a.deallocate(__p, __n); }
34648fb7bfaSmrg 
34748fb7bfaSmrg       /**
348a448f87cSmrg        *  @brief  Construct an object of type `_Tp`
34948fb7bfaSmrg        *  @param  __a  An allocator.
35048fb7bfaSmrg        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
35148fb7bfaSmrg        *  @param  __args Constructor arguments.
35248fb7bfaSmrg        *
35348fb7bfaSmrg        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
35448fb7bfaSmrg        *  if that expression is well-formed, otherwise uses placement-new
35548fb7bfaSmrg        *  to construct an object of type @a _Tp at location @a __p from the
35648fb7bfaSmrg        *  arguments @a __args...
35748fb7bfaSmrg       */
35848fb7bfaSmrg       template<typename _Tp, typename... _Args>
359fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR auto
360fb8a8121Smrg 	construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
361181254a7Smrg 	noexcept(noexcept(_S_construct(__a, __p,
362181254a7Smrg 				       std::forward<_Args>(__args)...)))
36348fb7bfaSmrg 	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
36448fb7bfaSmrg 	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
36548fb7bfaSmrg 
36648fb7bfaSmrg       /**
36748fb7bfaSmrg        *  @brief  Destroy an object of type @a _Tp
36848fb7bfaSmrg        *  @param  __a  An allocator.
36948fb7bfaSmrg        *  @param  __p  Pointer to the object to destroy
37048fb7bfaSmrg        *
37148fb7bfaSmrg        *  Calls @c __a.destroy(__p) if that expression is well-formed,
37248fb7bfaSmrg        *  otherwise calls @c __p->~_Tp()
37348fb7bfaSmrg       */
374f30ff588Smrg       template<typename _Tp>
375fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR void
376fb8a8121Smrg 	destroy(_Alloc& __a, _Tp* __p)
377181254a7Smrg 	noexcept(noexcept(_S_destroy(__a, __p, 0)))
378f9a78e0eSmrg 	{ _S_destroy(__a, __p, 0); }
37948fb7bfaSmrg 
38048fb7bfaSmrg       /**
38148fb7bfaSmrg        *  @brief  The maximum supported allocation size
38248fb7bfaSmrg        *  @param  __a  An allocator.
38348fb7bfaSmrg        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
38448fb7bfaSmrg        *
38548fb7bfaSmrg        *  Returns @c __a.max_size() if that expression is well-formed,
38648fb7bfaSmrg        *  otherwise returns @c numeric_limits<size_type>::max()
38748fb7bfaSmrg       */
388fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR size_type
389fb8a8121Smrg       max_size(const _Alloc& __a) noexcept
3904d5abbe8Smrg       { return _S_max_size(__a, 0); }
39148fb7bfaSmrg 
39248fb7bfaSmrg       /**
39348fb7bfaSmrg        *  @brief  Obtain an allocator to use when copying a container.
39448fb7bfaSmrg        *  @param  __rhs  An allocator.
39548fb7bfaSmrg        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
39648fb7bfaSmrg        *
39748fb7bfaSmrg        *  Returns @c __rhs.select_on_container_copy_construction() if that
39848fb7bfaSmrg        *  expression is well-formed, otherwise returns @a __rhs
39948fb7bfaSmrg       */
400fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR _Alloc
40148fb7bfaSmrg       select_on_container_copy_construction(const _Alloc& __rhs)
4024d5abbe8Smrg       { return _S_select(__rhs, 0); }
40348fb7bfaSmrg     };
40448fb7bfaSmrg 
405fb8a8121Smrg #if __cplusplus > 201703L
406fb8a8121Smrg # define __cpp_lib_constexpr_dynamic_alloc 201907L
407fb8a8121Smrg #endif
408fb8a8121Smrg 
409f30ff588Smrg   /// Partial specialization for std::allocator.
410f30ff588Smrg   template<typename _Tp>
411f30ff588Smrg     struct allocator_traits<allocator<_Tp>>
412f30ff588Smrg     {
413f30ff588Smrg       /// The allocator type
414f30ff588Smrg       using allocator_type = allocator<_Tp>;
415fb8a8121Smrg 
416f30ff588Smrg       /// The allocated type
417f30ff588Smrg       using value_type = _Tp;
418f30ff588Smrg 
419f30ff588Smrg       /// The allocator's pointer type.
420f30ff588Smrg       using pointer = _Tp*;
421f30ff588Smrg 
422f30ff588Smrg       /// The allocator's const pointer type.
423f30ff588Smrg       using const_pointer = const _Tp*;
424f30ff588Smrg 
425f30ff588Smrg       /// The allocator's void pointer type.
426f30ff588Smrg       using void_pointer = void*;
427f30ff588Smrg 
428f30ff588Smrg       /// The allocator's const void pointer type.
429f30ff588Smrg       using const_void_pointer = const void*;
430f30ff588Smrg 
431f30ff588Smrg       /// The allocator's difference type
432f30ff588Smrg       using difference_type = std::ptrdiff_t;
433f30ff588Smrg 
434f30ff588Smrg       /// The allocator's size type
435f30ff588Smrg       using size_type = std::size_t;
436f30ff588Smrg 
437f30ff588Smrg       /// How the allocator is propagated on copy assignment
438f30ff588Smrg       using propagate_on_container_copy_assignment = false_type;
439f30ff588Smrg 
440f30ff588Smrg       /// How the allocator is propagated on move assignment
441f30ff588Smrg       using propagate_on_container_move_assignment = true_type;
442f30ff588Smrg 
443f30ff588Smrg       /// How the allocator is propagated on swap
444f30ff588Smrg       using propagate_on_container_swap = false_type;
445f30ff588Smrg 
446f9a78e0eSmrg       /// Whether all instances of the allocator type compare equal.
447f9a78e0eSmrg       using is_always_equal = true_type;
448f9a78e0eSmrg 
449f30ff588Smrg       template<typename _Up>
450f30ff588Smrg 	using rebind_alloc = allocator<_Up>;
451f30ff588Smrg 
452f30ff588Smrg       template<typename _Up>
453f30ff588Smrg 	using rebind_traits = allocator_traits<allocator<_Up>>;
454f30ff588Smrg 
455f30ff588Smrg       /**
456f30ff588Smrg        *  @brief  Allocate memory.
457f30ff588Smrg        *  @param  __a  An allocator.
458f30ff588Smrg        *  @param  __n  The number of objects to allocate space for.
459f30ff588Smrg        *
460f30ff588Smrg        *  Calls @c a.allocate(n)
461f30ff588Smrg       */
462fb8a8121Smrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
463f30ff588Smrg       allocate(allocator_type& __a, size_type __n)
464f30ff588Smrg       { return __a.allocate(__n); }
465f30ff588Smrg 
466f30ff588Smrg       /**
467f30ff588Smrg        *  @brief  Allocate memory.
468f30ff588Smrg        *  @param  __a  An allocator.
469f30ff588Smrg        *  @param  __n  The number of objects to allocate space for.
470f30ff588Smrg        *  @param  __hint Aid to locality.
471f30ff588Smrg        *  @return Memory of suitable size and alignment for @a n objects
472f30ff588Smrg        *          of type @c value_type
473f30ff588Smrg        *
474f30ff588Smrg        *  Returns <tt> a.allocate(n, hint) </tt>
475f30ff588Smrg       */
476fb8a8121Smrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
477f30ff588Smrg       allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
478fb8a8121Smrg       {
479fb8a8121Smrg #if __cplusplus <= 201703L
480fb8a8121Smrg 	return __a.allocate(__n, __hint);
481fb8a8121Smrg #else
482fb8a8121Smrg 	return __a.allocate(__n);
483fb8a8121Smrg #endif
484fb8a8121Smrg       }
485f30ff588Smrg 
486f30ff588Smrg       /**
487f30ff588Smrg        *  @brief  Deallocate memory.
488f30ff588Smrg        *  @param  __a  An allocator.
489f30ff588Smrg        *  @param  __p  Pointer to the memory to deallocate.
490f30ff588Smrg        *  @param  __n  The number of objects space was allocated for.
491f30ff588Smrg        *
492f30ff588Smrg        *  Calls <tt> a.deallocate(p, n) </tt>
493f30ff588Smrg       */
494fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR void
495f30ff588Smrg       deallocate(allocator_type& __a, pointer __p, size_type __n)
496f30ff588Smrg       { __a.deallocate(__p, __n); }
497f30ff588Smrg 
498f30ff588Smrg       /**
499fb8a8121Smrg        *  @brief  Construct an object of type `_Up`
500f30ff588Smrg        *  @param  __a  An allocator.
501fb8a8121Smrg        *  @param  __p  Pointer to memory of suitable size and alignment for
502fb8a8121Smrg        *	       an object of type `_Up`.
503f30ff588Smrg        *  @param  __args Constructor arguments.
504f30ff588Smrg        *
505fb8a8121Smrg        *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
506fb8a8121Smrg        *  in C++11, C++14 and C++17. Changed in C++20 to call
507fb8a8121Smrg        *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
508f30ff588Smrg       */
509f30ff588Smrg       template<typename _Up, typename... _Args>
510fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR void
511fb8a8121Smrg 	construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
512fb8a8121Smrg 		  _Args&&... __args)
513fb8a8121Smrg 	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
514fb8a8121Smrg 	{
515fb8a8121Smrg #if __cplusplus <= 201703L
516fb8a8121Smrg 	  __a.construct(__p, std::forward<_Args>(__args)...);
517fb8a8121Smrg #else
518fb8a8121Smrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
519fb8a8121Smrg #endif
520fb8a8121Smrg 	}
521f30ff588Smrg 
522f30ff588Smrg       /**
523f30ff588Smrg        *  @brief  Destroy an object of type @a _Up
524f30ff588Smrg        *  @param  __a  An allocator.
525f30ff588Smrg        *  @param  __p  Pointer to the object to destroy
526f30ff588Smrg        *
527f30ff588Smrg        *  Calls @c __a.destroy(__p).
528f30ff588Smrg       */
529f30ff588Smrg       template<typename _Up>
530fb8a8121Smrg 	static _GLIBCXX20_CONSTEXPR void
531fb8a8121Smrg 	destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
532fb8a8121Smrg 	noexcept(is_nothrow_destructible<_Up>::value)
533fb8a8121Smrg 	{
534fb8a8121Smrg #if __cplusplus <= 201703L
535fb8a8121Smrg 	  __a.destroy(__p);
536fb8a8121Smrg #else
537fb8a8121Smrg 	  std::destroy_at(__p);
538fb8a8121Smrg #endif
539fb8a8121Smrg 	}
540f30ff588Smrg 
541f30ff588Smrg       /**
542f30ff588Smrg        *  @brief  The maximum supported allocation size
543f30ff588Smrg        *  @param  __a  An allocator.
544f30ff588Smrg        *  @return @c __a.max_size()
545f30ff588Smrg       */
546fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR size_type
547fb8a8121Smrg       max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
548fb8a8121Smrg       {
549fb8a8121Smrg #if __cplusplus <= 201703L
550fb8a8121Smrg 	return __a.max_size();
551fb8a8121Smrg #else
552fb8a8121Smrg 	return size_t(-1) / sizeof(value_type);
553fb8a8121Smrg #endif
554fb8a8121Smrg       }
555f30ff588Smrg 
556f30ff588Smrg       /**
557f30ff588Smrg        *  @brief  Obtain an allocator to use when copying a container.
558f30ff588Smrg        *  @param  __rhs  An allocator.
559f30ff588Smrg        *  @return @c __rhs
560f30ff588Smrg       */
561fb8a8121Smrg       static _GLIBCXX20_CONSTEXPR allocator_type
562f30ff588Smrg       select_on_container_copy_construction(const allocator_type& __rhs)
563f30ff588Smrg       { return __rhs; }
564f30ff588Smrg     };
565f30ff588Smrg 
566a448f87cSmrg   /// Explicit specialization for std::allocator<void>.
567a448f87cSmrg   template<>
568a448f87cSmrg     struct allocator_traits<allocator<void>>
569a448f87cSmrg     {
570a448f87cSmrg       /// The allocator type
571a448f87cSmrg       using allocator_type = allocator<void>;
572a448f87cSmrg 
573a448f87cSmrg       /// The allocated type
574a448f87cSmrg       using value_type = void;
575a448f87cSmrg 
576a448f87cSmrg       /// The allocator's pointer type.
577a448f87cSmrg       using pointer = void*;
578a448f87cSmrg 
579a448f87cSmrg       /// The allocator's const pointer type.
580a448f87cSmrg       using const_pointer = const void*;
581a448f87cSmrg 
582a448f87cSmrg       /// The allocator's void pointer type.
583a448f87cSmrg       using void_pointer = void*;
584a448f87cSmrg 
585a448f87cSmrg       /// The allocator's const void pointer type.
586a448f87cSmrg       using const_void_pointer = const void*;
587a448f87cSmrg 
588a448f87cSmrg       /// The allocator's difference type
589a448f87cSmrg       using difference_type = std::ptrdiff_t;
590a448f87cSmrg 
591a448f87cSmrg       /// The allocator's size type
592a448f87cSmrg       using size_type = std::size_t;
593a448f87cSmrg 
594a448f87cSmrg       /// How the allocator is propagated on copy assignment
595a448f87cSmrg       using propagate_on_container_copy_assignment = false_type;
596a448f87cSmrg 
597a448f87cSmrg       /// How the allocator is propagated on move assignment
598a448f87cSmrg       using propagate_on_container_move_assignment = true_type;
599a448f87cSmrg 
600a448f87cSmrg       /// How the allocator is propagated on swap
601a448f87cSmrg       using propagate_on_container_swap = false_type;
602a448f87cSmrg 
603a448f87cSmrg       /// Whether all instances of the allocator type compare equal.
604a448f87cSmrg       using is_always_equal = true_type;
605a448f87cSmrg 
606a448f87cSmrg       template<typename _Up>
607a448f87cSmrg 	using rebind_alloc = allocator<_Up>;
608a448f87cSmrg 
609a448f87cSmrg       template<typename _Up>
610a448f87cSmrg 	using rebind_traits = allocator_traits<allocator<_Up>>;
611a448f87cSmrg 
612a448f87cSmrg       /// allocate is ill-formed for allocator<void>
613a448f87cSmrg       static void*
614a448f87cSmrg       allocate(allocator_type&, size_type, const void* = nullptr) = delete;
615a448f87cSmrg 
616a448f87cSmrg       /// deallocate is ill-formed for allocator<void>
617a448f87cSmrg       static void
618a448f87cSmrg       deallocate(allocator_type&, void*, size_type) = delete;
619a448f87cSmrg 
620a448f87cSmrg       /**
621a448f87cSmrg        *  @brief  Construct an object of type `_Up`
622a448f87cSmrg        *  @param  __a  An allocator.
623a448f87cSmrg        *  @param  __p  Pointer to memory of suitable size and alignment for
624a448f87cSmrg        *	       an object of type `_Up`.
625a448f87cSmrg        *  @param  __args Constructor arguments.
626a448f87cSmrg        *
627a448f87cSmrg        *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
628a448f87cSmrg        *  in C++11, C++14 and C++17. Changed in C++20 to call
629a448f87cSmrg        *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
630a448f87cSmrg       */
631a448f87cSmrg       template<typename _Up, typename... _Args>
632a448f87cSmrg 	static _GLIBCXX20_CONSTEXPR void
633a448f87cSmrg 	construct(allocator_type&, _Up* __p, _Args&&... __args)
634a448f87cSmrg 	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
635b1e83836Smrg 	{ std::_Construct(__p, std::forward<_Args>(__args)...); }
636a448f87cSmrg 
637a448f87cSmrg       /**
638a448f87cSmrg        *  @brief  Destroy an object of type `_Up`
639a448f87cSmrg        *  @param  __a  An allocator.
640a448f87cSmrg        *  @param  __p  Pointer to the object to destroy
641a448f87cSmrg        *
642a448f87cSmrg        *  Invokes the destructor for `*__p`.
643a448f87cSmrg       */
644a448f87cSmrg       template<typename _Up>
645a448f87cSmrg 	static _GLIBCXX20_CONSTEXPR void
646a448f87cSmrg 	destroy(allocator_type&, _Up* __p)
647a448f87cSmrg 	noexcept(is_nothrow_destructible<_Up>::value)
648a448f87cSmrg 	{ std::_Destroy(__p); }
649a448f87cSmrg 
650a448f87cSmrg       /// max_size is ill-formed for allocator<void>
651a448f87cSmrg       static size_type
652a448f87cSmrg       max_size(const allocator_type&) = delete;
653a448f87cSmrg 
654a448f87cSmrg       /**
655a448f87cSmrg        *  @brief  Obtain an allocator to use when copying a container.
656a448f87cSmrg        *  @param  __rhs  An allocator.
657a448f87cSmrg        *  @return `__rhs`
658a448f87cSmrg       */
659a448f87cSmrg       static _GLIBCXX20_CONSTEXPR allocator_type
660a448f87cSmrg       select_on_container_copy_construction(const allocator_type& __rhs)
661a448f87cSmrg       { return __rhs; }
662a448f87cSmrg     };
663a448f87cSmrg 
664*0a307195Smrg   /// @cond undocumented
665fb8a8121Smrg #if __cplusplus < 201703L
66648fb7bfaSmrg   template<typename _Alloc>
66748fb7bfaSmrg     inline void
66848fb7bfaSmrg     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
66948fb7bfaSmrg     { __one = __two; }
67048fb7bfaSmrg 
67148fb7bfaSmrg   template<typename _Alloc>
67248fb7bfaSmrg     inline void
67348fb7bfaSmrg     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
67448fb7bfaSmrg     { }
675fb8a8121Smrg #endif
67648fb7bfaSmrg 
67748fb7bfaSmrg   template<typename _Alloc>
678fb8a8121Smrg     _GLIBCXX14_CONSTEXPR inline void
679fb8a8121Smrg     __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
68048fb7bfaSmrg     {
68148fb7bfaSmrg       typedef allocator_traits<_Alloc> __traits;
68248fb7bfaSmrg       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
683fb8a8121Smrg #if __cplusplus >= 201703L
684fb8a8121Smrg       if constexpr (__pocca::value)
685fb8a8121Smrg 	__one = __two;
686fb8a8121Smrg #else
68748fb7bfaSmrg       __do_alloc_on_copy(__one, __two, __pocca());
688fb8a8121Smrg #endif
68948fb7bfaSmrg     }
69048fb7bfaSmrg 
69148fb7bfaSmrg   template<typename _Alloc>
692fb8a8121Smrg     constexpr _Alloc
693fb8a8121Smrg     __alloc_on_copy(const _Alloc& __a)
69448fb7bfaSmrg     {
69548fb7bfaSmrg       typedef allocator_traits<_Alloc> __traits;
69648fb7bfaSmrg       return __traits::select_on_container_copy_construction(__a);
69748fb7bfaSmrg     }
69848fb7bfaSmrg 
699fb8a8121Smrg #if __cplusplus < 201703L
70048fb7bfaSmrg   template<typename _Alloc>
70148fb7bfaSmrg     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
70248fb7bfaSmrg     { __one = std::move(__two); }
70348fb7bfaSmrg 
70448fb7bfaSmrg   template<typename _Alloc>
70548fb7bfaSmrg     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
70648fb7bfaSmrg     { }
707fb8a8121Smrg #endif
70848fb7bfaSmrg 
70948fb7bfaSmrg   template<typename _Alloc>
710fb8a8121Smrg     _GLIBCXX14_CONSTEXPR inline void
711fb8a8121Smrg     __alloc_on_move(_Alloc& __one, _Alloc& __two)
71248fb7bfaSmrg     {
71348fb7bfaSmrg       typedef allocator_traits<_Alloc> __traits;
71448fb7bfaSmrg       typedef typename __traits::propagate_on_container_move_assignment __pocma;
715fb8a8121Smrg #if __cplusplus >= 201703L
716fb8a8121Smrg       if constexpr (__pocma::value)
717fb8a8121Smrg 	__one = std::move(__two);
718fb8a8121Smrg #else
71948fb7bfaSmrg       __do_alloc_on_move(__one, __two, __pocma());
720fb8a8121Smrg #endif
72148fb7bfaSmrg     }
72248fb7bfaSmrg 
723fb8a8121Smrg #if __cplusplus < 201703L
72448fb7bfaSmrg   template<typename _Alloc>
72548fb7bfaSmrg     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
72648fb7bfaSmrg     {
72748fb7bfaSmrg       using std::swap;
72848fb7bfaSmrg       swap(__one, __two);
72948fb7bfaSmrg     }
73048fb7bfaSmrg 
73148fb7bfaSmrg   template<typename _Alloc>
73248fb7bfaSmrg     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
73348fb7bfaSmrg     { }
734fb8a8121Smrg #endif
73548fb7bfaSmrg 
73648fb7bfaSmrg   template<typename _Alloc>
737fb8a8121Smrg     _GLIBCXX14_CONSTEXPR inline void
738fb8a8121Smrg     __alloc_on_swap(_Alloc& __one, _Alloc& __two)
73948fb7bfaSmrg     {
74048fb7bfaSmrg       typedef allocator_traits<_Alloc> __traits;
74148fb7bfaSmrg       typedef typename __traits::propagate_on_container_swap __pocs;
742fb8a8121Smrg #if __cplusplus >= 201703L
743fb8a8121Smrg       if constexpr (__pocs::value)
744fb8a8121Smrg 	{
745fb8a8121Smrg 	  using std::swap;
746fb8a8121Smrg 	  swap(__one, __two);
747fb8a8121Smrg 	}
748fb8a8121Smrg #else
74948fb7bfaSmrg       __do_alloc_on_swap(__one, __two, __pocs());
750fb8a8121Smrg #endif
75148fb7bfaSmrg     }
75248fb7bfaSmrg 
753181254a7Smrg   template<typename _Alloc, typename _Tp,
754181254a7Smrg 	   typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
755181254a7Smrg 	   typename = void>
756181254a7Smrg     struct __is_alloc_insertable_impl
757181254a7Smrg     : false_type
758181254a7Smrg     { };
75948fb7bfaSmrg 
760181254a7Smrg   template<typename _Alloc, typename _Tp, typename _ValueT>
761181254a7Smrg     struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
762181254a7Smrg       __void_t<decltype(allocator_traits<_Alloc>::construct(
763181254a7Smrg 		   std::declval<_Alloc&>(), std::declval<_ValueT*>(),
764181254a7Smrg 		   std::declval<_Tp>()))>>
765181254a7Smrg     : true_type
766181254a7Smrg     { };
76748fb7bfaSmrg 
76848fb7bfaSmrg   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
769181254a7Smrg   // (might be wrong if _Alloc::construct exists but is not constrained,
770181254a7Smrg   // i.e. actually trying to use it would still be invalid. Use with caution.)
77148fb7bfaSmrg   template<typename _Alloc>
77248fb7bfaSmrg     struct __is_copy_insertable
773181254a7Smrg     : __is_alloc_insertable_impl<_Alloc,
774181254a7Smrg 				 typename _Alloc::value_type const&>::type
77548fb7bfaSmrg     { };
77648fb7bfaSmrg 
77748fb7bfaSmrg   // std::allocator<_Tp> just requires CopyConstructible
77848fb7bfaSmrg   template<typename _Tp>
77948fb7bfaSmrg     struct __is_copy_insertable<allocator<_Tp>>
78048fb7bfaSmrg     : is_copy_constructible<_Tp>
78148fb7bfaSmrg     { };
78248fb7bfaSmrg 
783181254a7Smrg   // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
784181254a7Smrg   // (might be wrong if _Alloc::construct exists but is not constrained,
785181254a7Smrg   // i.e. actually trying to use it would still be invalid. Use with caution.)
786181254a7Smrg   template<typename _Alloc>
787181254a7Smrg     struct __is_move_insertable
788181254a7Smrg     : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
789181254a7Smrg     { };
790181254a7Smrg 
791181254a7Smrg   // std::allocator<_Tp> just requires MoveConstructible
792181254a7Smrg   template<typename _Tp>
793181254a7Smrg     struct __is_move_insertable<allocator<_Tp>>
794181254a7Smrg     : is_move_constructible<_Tp>
795181254a7Smrg     { };
796181254a7Smrg 
797a3e9eb18Smrg   // Trait to detect Allocator-like types.
798a3e9eb18Smrg   template<typename _Alloc, typename = void>
799a3e9eb18Smrg     struct __is_allocator : false_type { };
800a3e9eb18Smrg 
801a3e9eb18Smrg   template<typename _Alloc>
802a3e9eb18Smrg     struct __is_allocator<_Alloc,
803a3e9eb18Smrg       __void_t<typename _Alloc::value_type,
804a3e9eb18Smrg 	       decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
805a3e9eb18Smrg     : true_type { };
806a3e9eb18Smrg 
807a3e9eb18Smrg   template<typename _Alloc>
808a3e9eb18Smrg     using _RequireAllocator
809a3e9eb18Smrg       = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
810a3e9eb18Smrg 
811181254a7Smrg   template<typename _Alloc>
812181254a7Smrg     using _RequireNotAllocator
813181254a7Smrg       = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
814b1e83836Smrg 
815b1e83836Smrg #if __cpp_concepts >= 201907L
816b1e83836Smrg   template<typename _Alloc>
817b1e83836Smrg     concept __allocator_like = requires (_Alloc& __a) {
818b1e83836Smrg       typename _Alloc::value_type;
819b1e83836Smrg       __a.deallocate(__a.allocate(1u), 1u);
820b1e83836Smrg     };
821b1e83836Smrg #endif
822*0a307195Smrg   /// @endcond
823fb8a8121Smrg #endif // C++11
824fb8a8121Smrg 
825*0a307195Smrg   /// @cond undocumented
826*0a307195Smrg 
827fb8a8121Smrg   /**
828fb8a8121Smrg    * Destroy a range of objects using the supplied allocator.  For
829fb8a8121Smrg    * non-default allocators we do not optimize away invocation of
830fb8a8121Smrg    * destroy() even if _Tp has a trivial destructor.
831fb8a8121Smrg    */
832fb8a8121Smrg 
833fb8a8121Smrg   template<typename _ForwardIterator, typename _Allocator>
834b1e83836Smrg     _GLIBCXX20_CONSTEXPR
835fb8a8121Smrg     void
836fb8a8121Smrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
837fb8a8121Smrg 	     _Allocator& __alloc)
838fb8a8121Smrg     {
839fb8a8121Smrg       for (; __first != __last; ++__first)
840fb8a8121Smrg #if __cplusplus < 201103L
841fb8a8121Smrg 	__alloc.destroy(std::__addressof(*__first));
842fb8a8121Smrg #else
843fb8a8121Smrg 	allocator_traits<_Allocator>::destroy(__alloc,
844fb8a8121Smrg 					      std::__addressof(*__first));
845fb8a8121Smrg #endif
846fb8a8121Smrg     }
847fb8a8121Smrg 
848fb8a8121Smrg   template<typename _ForwardIterator, typename _Tp>
849b1e83836Smrg     _GLIBCXX20_CONSTEXPR
850fb8a8121Smrg     inline void
851fb8a8121Smrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
852fb8a8121Smrg 	     allocator<_Tp>&)
853fb8a8121Smrg     {
854*0a307195Smrg       std::_Destroy(__first, __last);
855fb8a8121Smrg     }
856*0a307195Smrg   /// @endcond
857181254a7Smrg 
85848fb7bfaSmrg _GLIBCXX_END_NAMESPACE_VERSION
85948fb7bfaSmrg } // namespace std
860a3e9eb18Smrg #endif // _ALLOC_TRAITS_H
861