xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/alloc_traits.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg // Allocator traits -*- C++ -*-
21debfc3dSmrg 
3*8feb0f0bSmrg // Copyright (C) 2011-2020 Free Software Foundation, Inc.
41debfc3dSmrg //
51debfc3dSmrg // This file is part of the GNU ISO C++ Library.  This library is free
61debfc3dSmrg // software; you can redistribute it and/or modify it under the
71debfc3dSmrg // terms of the GNU General Public License as published by the
81debfc3dSmrg // Free Software Foundation; either version 3, or (at your option)
91debfc3dSmrg // any later version.
101debfc3dSmrg 
111debfc3dSmrg // This library is distributed in the hope that it will be useful,
121debfc3dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
131debfc3dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
141debfc3dSmrg // GNU General Public License for more details.
151debfc3dSmrg 
161debfc3dSmrg // Under Section 7 of GPL version 3, you are granted additional
171debfc3dSmrg // permissions described in the GCC Runtime Library Exception, version
181debfc3dSmrg // 3.1, as published by the Free Software Foundation.
191debfc3dSmrg 
201debfc3dSmrg // You should have received a copy of the GNU General Public License and
211debfc3dSmrg // a copy of the GCC Runtime Library Exception along with this program;
221debfc3dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
231debfc3dSmrg // <http://www.gnu.org/licenses/>.
241debfc3dSmrg 
251debfc3dSmrg /** @file bits/alloc_traits.h
261debfc3dSmrg  *  This is an internal header file, included by other library headers.
271debfc3dSmrg  *  Do not attempt to use it directly. @headername{memory}
281debfc3dSmrg  */
291debfc3dSmrg 
301debfc3dSmrg #ifndef _ALLOC_TRAITS_H
311debfc3dSmrg #define _ALLOC_TRAITS_H 1
321debfc3dSmrg 
33*8feb0f0bSmrg #include <bits/stl_construct.h>
341debfc3dSmrg #include <bits/memoryfwd.h>
35*8feb0f0bSmrg #if __cplusplus >= 201103L
36*8feb0f0bSmrg # include <bits/allocator.h>
371debfc3dSmrg # include <bits/ptr_traits.h>
381debfc3dSmrg # include <ext/numeric_traits.h>
39*8feb0f0bSmrg #endif
401debfc3dSmrg 
_GLIBCXX_VISIBILITY(default)411debfc3dSmrg namespace std _GLIBCXX_VISIBILITY(default)
421debfc3dSmrg {
431debfc3dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
441debfc3dSmrg 
45*8feb0f0bSmrg #if __cplusplus >= 201103L
46*8feb0f0bSmrg #define __cpp_lib_allocator_traits_is_always_equal 201411
47*8feb0f0bSmrg 
481debfc3dSmrg   struct __allocator_traits_base
491debfc3dSmrg   {
501debfc3dSmrg     template<typename _Tp, typename _Up, typename = void>
511debfc3dSmrg       struct __rebind : __replace_first_arg<_Tp, _Up> { };
521debfc3dSmrg 
531debfc3dSmrg     template<typename _Tp, typename _Up>
541debfc3dSmrg       struct __rebind<_Tp, _Up,
551debfc3dSmrg 		      __void_t<typename _Tp::template rebind<_Up>::other>>
561debfc3dSmrg       { using type = typename _Tp::template rebind<_Up>::other; };
571debfc3dSmrg 
581debfc3dSmrg   protected:
591debfc3dSmrg     template<typename _Tp>
601debfc3dSmrg       using __pointer = typename _Tp::pointer;
611debfc3dSmrg     template<typename _Tp>
621debfc3dSmrg       using __c_pointer = typename _Tp::const_pointer;
631debfc3dSmrg     template<typename _Tp>
641debfc3dSmrg       using __v_pointer = typename _Tp::void_pointer;
651debfc3dSmrg     template<typename _Tp>
661debfc3dSmrg       using __cv_pointer = typename _Tp::const_void_pointer;
671debfc3dSmrg     template<typename _Tp>
681debfc3dSmrg       using __pocca = typename _Tp::propagate_on_container_copy_assignment;
691debfc3dSmrg     template<typename _Tp>
701debfc3dSmrg       using __pocma = typename _Tp::propagate_on_container_move_assignment;
711debfc3dSmrg     template<typename _Tp>
721debfc3dSmrg       using __pocs = typename _Tp::propagate_on_container_swap;
731debfc3dSmrg     template<typename _Tp>
741debfc3dSmrg       using __equal = typename _Tp::is_always_equal;
751debfc3dSmrg   };
761debfc3dSmrg 
771debfc3dSmrg   template<typename _Alloc, typename _Up>
781debfc3dSmrg     using __alloc_rebind
791debfc3dSmrg       = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
801debfc3dSmrg 
811debfc3dSmrg   /**
821debfc3dSmrg    * @brief  Uniform interface to all allocator types.
831debfc3dSmrg    * @ingroup allocators
841debfc3dSmrg   */
851debfc3dSmrg   template<typename _Alloc>
861debfc3dSmrg     struct allocator_traits : __allocator_traits_base
871debfc3dSmrg     {
881debfc3dSmrg       /// The allocator type
891debfc3dSmrg       typedef _Alloc allocator_type;
901debfc3dSmrg       /// The allocated type
911debfc3dSmrg       typedef typename _Alloc::value_type value_type;
921debfc3dSmrg 
931debfc3dSmrg       /**
941debfc3dSmrg        * @brief   The allocator's pointer type.
951debfc3dSmrg        *
961debfc3dSmrg        * @c Alloc::pointer if that type exists, otherwise @c value_type*
971debfc3dSmrg       */
981debfc3dSmrg       using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
991debfc3dSmrg 
1001debfc3dSmrg     private:
1011debfc3dSmrg       // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp>
1021debfc3dSmrg       template<template<typename> class _Func, typename _Tp, typename = void>
1031debfc3dSmrg 	struct _Ptr
1041debfc3dSmrg 	{
1051debfc3dSmrg 	  using type = typename pointer_traits<pointer>::template rebind<_Tp>;
1061debfc3dSmrg 	};
1071debfc3dSmrg 
1081debfc3dSmrg       template<template<typename> class _Func, typename _Tp>
1091debfc3dSmrg 	struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
1101debfc3dSmrg 	{
1111debfc3dSmrg 	  using type = _Func<_Alloc>;
1121debfc3dSmrg 	};
1131debfc3dSmrg 
1141debfc3dSmrg       // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type
1151debfc3dSmrg       template<typename _A2, typename _PtrT, typename = void>
1161debfc3dSmrg 	struct _Diff
1171debfc3dSmrg 	{ using type = typename pointer_traits<_PtrT>::difference_type; };
1181debfc3dSmrg 
1191debfc3dSmrg       template<typename _A2, typename _PtrT>
1201debfc3dSmrg 	struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>>
1211debfc3dSmrg 	{ using type = typename _A2::difference_type; };
1221debfc3dSmrg 
1231debfc3dSmrg       // Select _A2::size_type or make_unsigned<_DiffT>::type
1241debfc3dSmrg       template<typename _A2, typename _DiffT, typename = void>
1251debfc3dSmrg 	struct _Size : make_unsigned<_DiffT> { };
1261debfc3dSmrg 
1271debfc3dSmrg       template<typename _A2, typename _DiffT>
1281debfc3dSmrg 	struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>>
1291debfc3dSmrg 	{ using type = typename _A2::size_type; };
1301debfc3dSmrg 
1311debfc3dSmrg     public:
1321debfc3dSmrg       /**
1331debfc3dSmrg        * @brief   The allocator's const pointer type.
1341debfc3dSmrg        *
1351debfc3dSmrg        * @c Alloc::const_pointer if that type exists, otherwise
1361debfc3dSmrg        * <tt> pointer_traits<pointer>::rebind<const value_type> </tt>
1371debfc3dSmrg       */
1381debfc3dSmrg       using const_pointer = typename _Ptr<__c_pointer, const value_type>::type;
1391debfc3dSmrg 
1401debfc3dSmrg       /**
1411debfc3dSmrg        * @brief   The allocator's void pointer type.
1421debfc3dSmrg        *
1431debfc3dSmrg        * @c Alloc::void_pointer if that type exists, otherwise
1441debfc3dSmrg        * <tt> pointer_traits<pointer>::rebind<void> </tt>
1451debfc3dSmrg       */
1461debfc3dSmrg       using void_pointer = typename _Ptr<__v_pointer, void>::type;
1471debfc3dSmrg 
1481debfc3dSmrg       /**
1491debfc3dSmrg        * @brief   The allocator's const void pointer type.
1501debfc3dSmrg        *
1511debfc3dSmrg        * @c Alloc::const_void_pointer if that type exists, otherwise
1521debfc3dSmrg        * <tt> pointer_traits<pointer>::rebind<const void> </tt>
1531debfc3dSmrg       */
1541debfc3dSmrg       using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type;
1551debfc3dSmrg 
1561debfc3dSmrg       /**
1571debfc3dSmrg        * @brief   The allocator's difference type
1581debfc3dSmrg        *
1591debfc3dSmrg        * @c Alloc::difference_type if that type exists, otherwise
1601debfc3dSmrg        * <tt> pointer_traits<pointer>::difference_type </tt>
1611debfc3dSmrg       */
1621debfc3dSmrg       using difference_type = typename _Diff<_Alloc, pointer>::type;
1631debfc3dSmrg 
1641debfc3dSmrg       /**
1651debfc3dSmrg        * @brief   The allocator's size type
1661debfc3dSmrg        *
1671debfc3dSmrg        * @c Alloc::size_type if that type exists, otherwise
1681debfc3dSmrg        * <tt> make_unsigned<difference_type>::type </tt>
1691debfc3dSmrg       */
1701debfc3dSmrg       using size_type = typename _Size<_Alloc, difference_type>::type;
1711debfc3dSmrg 
1721debfc3dSmrg       /**
1731debfc3dSmrg        * @brief   How the allocator is propagated on copy assignment
1741debfc3dSmrg        *
1751debfc3dSmrg        * @c Alloc::propagate_on_container_copy_assignment if that type exists,
1761debfc3dSmrg        * otherwise @c false_type
1771debfc3dSmrg       */
1781debfc3dSmrg       using propagate_on_container_copy_assignment
1791debfc3dSmrg 	= __detected_or_t<false_type, __pocca, _Alloc>;
1801debfc3dSmrg 
1811debfc3dSmrg       /**
1821debfc3dSmrg        * @brief   How the allocator is propagated on move assignment
1831debfc3dSmrg        *
1841debfc3dSmrg        * @c Alloc::propagate_on_container_move_assignment if that type exists,
1851debfc3dSmrg        * otherwise @c false_type
1861debfc3dSmrg       */
1871debfc3dSmrg       using propagate_on_container_move_assignment
1881debfc3dSmrg 	= __detected_or_t<false_type, __pocma, _Alloc>;
1891debfc3dSmrg 
1901debfc3dSmrg       /**
1911debfc3dSmrg        * @brief   How the allocator is propagated on swap
1921debfc3dSmrg        *
1931debfc3dSmrg        * @c Alloc::propagate_on_container_swap if that type exists,
1941debfc3dSmrg        * otherwise @c false_type
1951debfc3dSmrg       */
1961debfc3dSmrg       using propagate_on_container_swap
1971debfc3dSmrg 	= __detected_or_t<false_type, __pocs, _Alloc>;
1981debfc3dSmrg 
1991debfc3dSmrg       /**
2001debfc3dSmrg        * @brief   Whether all instances of the allocator type compare equal.
2011debfc3dSmrg        *
2021debfc3dSmrg        * @c Alloc::is_always_equal if that type exists,
2031debfc3dSmrg        * otherwise @c is_empty<Alloc>::type
2041debfc3dSmrg       */
2051debfc3dSmrg       using is_always_equal
2061debfc3dSmrg 	= __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>;
2071debfc3dSmrg 
2081debfc3dSmrg       template<typename _Tp>
2091debfc3dSmrg 	using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
2101debfc3dSmrg       template<typename _Tp>
2111debfc3dSmrg 	using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
2121debfc3dSmrg 
2131debfc3dSmrg     private:
2141debfc3dSmrg       template<typename _Alloc2>
215*8feb0f0bSmrg 	static constexpr auto
2161debfc3dSmrg 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int)
2171debfc3dSmrg 	-> decltype(__a.allocate(__n, __hint))
2181debfc3dSmrg 	{ return __a.allocate(__n, __hint); }
2191debfc3dSmrg 
2201debfc3dSmrg       template<typename _Alloc2>
221*8feb0f0bSmrg 	static constexpr pointer
2221debfc3dSmrg 	_S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...)
2231debfc3dSmrg 	{ return __a.allocate(__n); }
2241debfc3dSmrg 
2251debfc3dSmrg       template<typename _Tp, typename... _Args>
2261debfc3dSmrg 	struct __construct_helper
2271debfc3dSmrg 	{
2281debfc3dSmrg 	  template<typename _Alloc2,
2291debfc3dSmrg 	    typename = decltype(std::declval<_Alloc2*>()->construct(
2301debfc3dSmrg 		  std::declval<_Tp*>(), std::declval<_Args>()...))>
2311debfc3dSmrg 	    static true_type __test(int);
2321debfc3dSmrg 
2331debfc3dSmrg 	  template<typename>
2341debfc3dSmrg 	    static false_type __test(...);
2351debfc3dSmrg 
2361debfc3dSmrg 	  using type = decltype(__test<_Alloc>(0));
2371debfc3dSmrg 	};
2381debfc3dSmrg 
2391debfc3dSmrg       template<typename _Tp, typename... _Args>
2401debfc3dSmrg 	using __has_construct
2411debfc3dSmrg 	  = typename __construct_helper<_Tp, _Args...>::type;
2421debfc3dSmrg 
2431debfc3dSmrg       template<typename _Tp, typename... _Args>
244*8feb0f0bSmrg 	static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>>
2451debfc3dSmrg 	_S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
246c0a68be4Smrg 	noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
2471debfc3dSmrg 	{ __a.construct(__p, std::forward<_Args>(__args)...); }
2481debfc3dSmrg 
2491debfc3dSmrg       template<typename _Tp, typename... _Args>
250*8feb0f0bSmrg 	static _GLIBCXX14_CONSTEXPR
2511debfc3dSmrg 	_Require<__and_<__not_<__has_construct<_Tp, _Args...>>,
2521debfc3dSmrg 			       is_constructible<_Tp, _Args...>>>
2531debfc3dSmrg 	_S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
254*8feb0f0bSmrg 	noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value)
255*8feb0f0bSmrg 	{
256*8feb0f0bSmrg #if __cplusplus <= 201703L
257*8feb0f0bSmrg 	  ::new((void*)__p) _Tp(std::forward<_Args>(__args)...);
258*8feb0f0bSmrg #else
259*8feb0f0bSmrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
260*8feb0f0bSmrg #endif
261*8feb0f0bSmrg 	}
2621debfc3dSmrg 
2631debfc3dSmrg       template<typename _Alloc2, typename _Tp>
264*8feb0f0bSmrg 	static _GLIBCXX14_CONSTEXPR auto
2651debfc3dSmrg 	_S_destroy(_Alloc2& __a, _Tp* __p, int)
266c0a68be4Smrg 	noexcept(noexcept(__a.destroy(__p)))
2671debfc3dSmrg 	-> decltype(__a.destroy(__p))
2681debfc3dSmrg 	{ __a.destroy(__p); }
2691debfc3dSmrg 
2701debfc3dSmrg       template<typename _Alloc2, typename _Tp>
271*8feb0f0bSmrg 	static _GLIBCXX14_CONSTEXPR void
2721debfc3dSmrg 	_S_destroy(_Alloc2&, _Tp* __p, ...)
273*8feb0f0bSmrg 	noexcept(std::is_nothrow_destructible<_Tp>::value)
274*8feb0f0bSmrg 	{ std::_Destroy(__p); }
2751debfc3dSmrg 
2761debfc3dSmrg       template<typename _Alloc2>
277*8feb0f0bSmrg 	static constexpr auto
2781debfc3dSmrg 	_S_max_size(_Alloc2& __a, int)
2791debfc3dSmrg 	-> decltype(__a.max_size())
2801debfc3dSmrg 	{ return __a.max_size(); }
2811debfc3dSmrg 
2821debfc3dSmrg       template<typename _Alloc2>
283*8feb0f0bSmrg 	static constexpr size_type
2841debfc3dSmrg 	_S_max_size(_Alloc2&, ...)
2851debfc3dSmrg 	{
2861debfc3dSmrg 	  // _GLIBCXX_RESOLVE_LIB_DEFECTS
2871debfc3dSmrg 	  // 2466. allocator_traits::max_size() default behavior is incorrect
2881debfc3dSmrg 	  return __gnu_cxx::__numeric_traits<size_type>::__max
2891debfc3dSmrg 	    / sizeof(value_type);
2901debfc3dSmrg 	}
2911debfc3dSmrg 
2921debfc3dSmrg       template<typename _Alloc2>
293*8feb0f0bSmrg 	static constexpr auto
2941debfc3dSmrg 	_S_select(_Alloc2& __a, int)
2951debfc3dSmrg 	-> decltype(__a.select_on_container_copy_construction())
2961debfc3dSmrg 	{ return __a.select_on_container_copy_construction(); }
2971debfc3dSmrg 
2981debfc3dSmrg       template<typename _Alloc2>
299*8feb0f0bSmrg 	static constexpr _Alloc2
3001debfc3dSmrg 	_S_select(_Alloc2& __a, ...)
3011debfc3dSmrg 	{ return __a; }
3021debfc3dSmrg 
3031debfc3dSmrg     public:
3041debfc3dSmrg 
3051debfc3dSmrg       /**
3061debfc3dSmrg        *  @brief  Allocate memory.
3071debfc3dSmrg        *  @param  __a  An allocator.
3081debfc3dSmrg        *  @param  __n  The number of objects to allocate space for.
3091debfc3dSmrg        *
3101debfc3dSmrg        *  Calls @c a.allocate(n)
3111debfc3dSmrg       */
312*8feb0f0bSmrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
3131debfc3dSmrg       allocate(_Alloc& __a, size_type __n)
3141debfc3dSmrg       { return __a.allocate(__n); }
3151debfc3dSmrg 
3161debfc3dSmrg       /**
3171debfc3dSmrg        *  @brief  Allocate memory.
3181debfc3dSmrg        *  @param  __a  An allocator.
3191debfc3dSmrg        *  @param  __n  The number of objects to allocate space for.
3201debfc3dSmrg        *  @param  __hint Aid to locality.
3211debfc3dSmrg        *  @return Memory of suitable size and alignment for @a n objects
3221debfc3dSmrg        *          of type @c value_type
3231debfc3dSmrg        *
3241debfc3dSmrg        *  Returns <tt> a.allocate(n, hint) </tt> if that expression is
3251debfc3dSmrg        *  well-formed, otherwise returns @c a.allocate(n)
3261debfc3dSmrg       */
327*8feb0f0bSmrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
3281debfc3dSmrg       allocate(_Alloc& __a, size_type __n, const_void_pointer __hint)
3291debfc3dSmrg       { return _S_allocate(__a, __n, __hint, 0); }
3301debfc3dSmrg 
3311debfc3dSmrg       /**
3321debfc3dSmrg        *  @brief  Deallocate memory.
3331debfc3dSmrg        *  @param  __a  An allocator.
3341debfc3dSmrg        *  @param  __p  Pointer to the memory to deallocate.
3351debfc3dSmrg        *  @param  __n  The number of objects space was allocated for.
3361debfc3dSmrg        *
3371debfc3dSmrg        *  Calls <tt> a.deallocate(p, n) </tt>
3381debfc3dSmrg       */
339*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR void
3401debfc3dSmrg       deallocate(_Alloc& __a, pointer __p, size_type __n)
3411debfc3dSmrg       { __a.deallocate(__p, __n); }
3421debfc3dSmrg 
3431debfc3dSmrg       /**
344*8feb0f0bSmrg        *  @brief  Construct an object of type `_Tp`
3451debfc3dSmrg        *  @param  __a  An allocator.
3461debfc3dSmrg        *  @param  __p  Pointer to memory of suitable size and alignment for Tp
3471debfc3dSmrg        *  @param  __args Constructor arguments.
3481debfc3dSmrg        *
3491debfc3dSmrg        *  Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt>
3501debfc3dSmrg        *  if that expression is well-formed, otherwise uses placement-new
3511debfc3dSmrg        *  to construct an object of type @a _Tp at location @a __p from the
3521debfc3dSmrg        *  arguments @a __args...
3531debfc3dSmrg       */
3541debfc3dSmrg       template<typename _Tp, typename... _Args>
355*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR auto
356*8feb0f0bSmrg 	construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
357c0a68be4Smrg 	noexcept(noexcept(_S_construct(__a, __p,
358c0a68be4Smrg 				       std::forward<_Args>(__args)...)))
3591debfc3dSmrg 	-> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...))
3601debfc3dSmrg 	{ _S_construct(__a, __p, std::forward<_Args>(__args)...); }
3611debfc3dSmrg 
3621debfc3dSmrg       /**
3631debfc3dSmrg        *  @brief  Destroy an object of type @a _Tp
3641debfc3dSmrg        *  @param  __a  An allocator.
3651debfc3dSmrg        *  @param  __p  Pointer to the object to destroy
3661debfc3dSmrg        *
3671debfc3dSmrg        *  Calls @c __a.destroy(__p) if that expression is well-formed,
3681debfc3dSmrg        *  otherwise calls @c __p->~_Tp()
3691debfc3dSmrg       */
3701debfc3dSmrg       template<typename _Tp>
371*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR void
372*8feb0f0bSmrg 	destroy(_Alloc& __a, _Tp* __p)
373c0a68be4Smrg 	noexcept(noexcept(_S_destroy(__a, __p, 0)))
3741debfc3dSmrg 	{ _S_destroy(__a, __p, 0); }
3751debfc3dSmrg 
3761debfc3dSmrg       /**
3771debfc3dSmrg        *  @brief  The maximum supported allocation size
3781debfc3dSmrg        *  @param  __a  An allocator.
3791debfc3dSmrg        *  @return @c __a.max_size() or @c numeric_limits<size_type>::max()
3801debfc3dSmrg        *
3811debfc3dSmrg        *  Returns @c __a.max_size() if that expression is well-formed,
3821debfc3dSmrg        *  otherwise returns @c numeric_limits<size_type>::max()
3831debfc3dSmrg       */
384*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR size_type
385*8feb0f0bSmrg       max_size(const _Alloc& __a) noexcept
3861debfc3dSmrg       { return _S_max_size(__a, 0); }
3871debfc3dSmrg 
3881debfc3dSmrg       /**
3891debfc3dSmrg        *  @brief  Obtain an allocator to use when copying a container.
3901debfc3dSmrg        *  @param  __rhs  An allocator.
3911debfc3dSmrg        *  @return @c __rhs.select_on_container_copy_construction() or @a __rhs
3921debfc3dSmrg        *
3931debfc3dSmrg        *  Returns @c __rhs.select_on_container_copy_construction() if that
3941debfc3dSmrg        *  expression is well-formed, otherwise returns @a __rhs
3951debfc3dSmrg       */
396*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR _Alloc
3971debfc3dSmrg       select_on_container_copy_construction(const _Alloc& __rhs)
3981debfc3dSmrg       { return _S_select(__rhs, 0); }
3991debfc3dSmrg     };
4001debfc3dSmrg 
401*8feb0f0bSmrg #if __cplusplus > 201703L
402*8feb0f0bSmrg # define __cpp_lib_constexpr_dynamic_alloc 201907L
403*8feb0f0bSmrg #endif
404*8feb0f0bSmrg 
4051debfc3dSmrg   /// Partial specialization for std::allocator.
4061debfc3dSmrg   template<typename _Tp>
4071debfc3dSmrg     struct allocator_traits<allocator<_Tp>>
4081debfc3dSmrg     {
4091debfc3dSmrg       /// The allocator type
4101debfc3dSmrg       using allocator_type = allocator<_Tp>;
411*8feb0f0bSmrg 
4121debfc3dSmrg       /// The allocated type
4131debfc3dSmrg       using value_type = _Tp;
4141debfc3dSmrg 
4151debfc3dSmrg       /// The allocator's pointer type.
4161debfc3dSmrg       using pointer = _Tp*;
4171debfc3dSmrg 
4181debfc3dSmrg       /// The allocator's const pointer type.
4191debfc3dSmrg       using const_pointer = const _Tp*;
4201debfc3dSmrg 
4211debfc3dSmrg       /// The allocator's void pointer type.
4221debfc3dSmrg       using void_pointer = void*;
4231debfc3dSmrg 
4241debfc3dSmrg       /// The allocator's const void pointer type.
4251debfc3dSmrg       using const_void_pointer = const void*;
4261debfc3dSmrg 
4271debfc3dSmrg       /// The allocator's difference type
4281debfc3dSmrg       using difference_type = std::ptrdiff_t;
4291debfc3dSmrg 
4301debfc3dSmrg       /// The allocator's size type
4311debfc3dSmrg       using size_type = std::size_t;
4321debfc3dSmrg 
4331debfc3dSmrg       /// How the allocator is propagated on copy assignment
4341debfc3dSmrg       using propagate_on_container_copy_assignment = false_type;
4351debfc3dSmrg 
4361debfc3dSmrg       /// How the allocator is propagated on move assignment
4371debfc3dSmrg       using propagate_on_container_move_assignment = true_type;
4381debfc3dSmrg 
4391debfc3dSmrg       /// How the allocator is propagated on swap
4401debfc3dSmrg       using propagate_on_container_swap = false_type;
4411debfc3dSmrg 
4421debfc3dSmrg       /// Whether all instances of the allocator type compare equal.
4431debfc3dSmrg       using is_always_equal = true_type;
4441debfc3dSmrg 
4451debfc3dSmrg       template<typename _Up>
4461debfc3dSmrg 	using rebind_alloc = allocator<_Up>;
4471debfc3dSmrg 
4481debfc3dSmrg       template<typename _Up>
4491debfc3dSmrg 	using rebind_traits = allocator_traits<allocator<_Up>>;
4501debfc3dSmrg 
4511debfc3dSmrg       /**
4521debfc3dSmrg        *  @brief  Allocate memory.
4531debfc3dSmrg        *  @param  __a  An allocator.
4541debfc3dSmrg        *  @param  __n  The number of objects to allocate space for.
4551debfc3dSmrg        *
4561debfc3dSmrg        *  Calls @c a.allocate(n)
4571debfc3dSmrg       */
458*8feb0f0bSmrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
4591debfc3dSmrg       allocate(allocator_type& __a, size_type __n)
4601debfc3dSmrg       { return __a.allocate(__n); }
4611debfc3dSmrg 
4621debfc3dSmrg       /**
4631debfc3dSmrg        *  @brief  Allocate memory.
4641debfc3dSmrg        *  @param  __a  An allocator.
4651debfc3dSmrg        *  @param  __n  The number of objects to allocate space for.
4661debfc3dSmrg        *  @param  __hint Aid to locality.
4671debfc3dSmrg        *  @return Memory of suitable size and alignment for @a n objects
4681debfc3dSmrg        *          of type @c value_type
4691debfc3dSmrg        *
4701debfc3dSmrg        *  Returns <tt> a.allocate(n, hint) </tt>
4711debfc3dSmrg       */
472*8feb0f0bSmrg       _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer
4731debfc3dSmrg       allocate(allocator_type& __a, size_type __n, const_void_pointer __hint)
474*8feb0f0bSmrg       {
475*8feb0f0bSmrg #if __cplusplus <= 201703L
476*8feb0f0bSmrg 	return __a.allocate(__n, __hint);
477*8feb0f0bSmrg #else
478*8feb0f0bSmrg 	return __a.allocate(__n);
479*8feb0f0bSmrg #endif
480*8feb0f0bSmrg       }
4811debfc3dSmrg 
4821debfc3dSmrg       /**
4831debfc3dSmrg        *  @brief  Deallocate memory.
4841debfc3dSmrg        *  @param  __a  An allocator.
4851debfc3dSmrg        *  @param  __p  Pointer to the memory to deallocate.
4861debfc3dSmrg        *  @param  __n  The number of objects space was allocated for.
4871debfc3dSmrg        *
4881debfc3dSmrg        *  Calls <tt> a.deallocate(p, n) </tt>
4891debfc3dSmrg       */
490*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR void
4911debfc3dSmrg       deallocate(allocator_type& __a, pointer __p, size_type __n)
4921debfc3dSmrg       { __a.deallocate(__p, __n); }
4931debfc3dSmrg 
4941debfc3dSmrg       /**
495*8feb0f0bSmrg        *  @brief  Construct an object of type `_Up`
4961debfc3dSmrg        *  @param  __a  An allocator.
497*8feb0f0bSmrg        *  @param  __p  Pointer to memory of suitable size and alignment for
498*8feb0f0bSmrg        *	       an object of type `_Up`.
4991debfc3dSmrg        *  @param  __args Constructor arguments.
5001debfc3dSmrg        *
501*8feb0f0bSmrg        *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
502*8feb0f0bSmrg        *  in C++11, C++14 and C++17. Changed in C++20 to call
503*8feb0f0bSmrg        *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
5041debfc3dSmrg       */
5051debfc3dSmrg       template<typename _Up, typename... _Args>
506*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR void
507*8feb0f0bSmrg 	construct(allocator_type& __a __attribute__((__unused__)), _Up* __p,
508*8feb0f0bSmrg 		  _Args&&... __args)
509*8feb0f0bSmrg 	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
510*8feb0f0bSmrg 	{
511*8feb0f0bSmrg #if __cplusplus <= 201703L
512*8feb0f0bSmrg 	  __a.construct(__p, std::forward<_Args>(__args)...);
513*8feb0f0bSmrg #else
514*8feb0f0bSmrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
515*8feb0f0bSmrg #endif
516*8feb0f0bSmrg 	}
5171debfc3dSmrg 
5181debfc3dSmrg       /**
5191debfc3dSmrg        *  @brief  Destroy an object of type @a _Up
5201debfc3dSmrg        *  @param  __a  An allocator.
5211debfc3dSmrg        *  @param  __p  Pointer to the object to destroy
5221debfc3dSmrg        *
5231debfc3dSmrg        *  Calls @c __a.destroy(__p).
5241debfc3dSmrg       */
5251debfc3dSmrg       template<typename _Up>
526*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR void
527*8feb0f0bSmrg 	destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p)
528*8feb0f0bSmrg 	noexcept(is_nothrow_destructible<_Up>::value)
529*8feb0f0bSmrg 	{
530*8feb0f0bSmrg #if __cplusplus <= 201703L
531*8feb0f0bSmrg 	  __a.destroy(__p);
532*8feb0f0bSmrg #else
533*8feb0f0bSmrg 	  std::destroy_at(__p);
534*8feb0f0bSmrg #endif
535*8feb0f0bSmrg 	}
5361debfc3dSmrg 
5371debfc3dSmrg       /**
5381debfc3dSmrg        *  @brief  The maximum supported allocation size
5391debfc3dSmrg        *  @param  __a  An allocator.
5401debfc3dSmrg        *  @return @c __a.max_size()
5411debfc3dSmrg       */
542*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR size_type
543*8feb0f0bSmrg       max_size(const allocator_type& __a __attribute__((__unused__))) noexcept
544*8feb0f0bSmrg       {
545*8feb0f0bSmrg #if __cplusplus <= 201703L
546*8feb0f0bSmrg 	return __a.max_size();
547*8feb0f0bSmrg #else
548*8feb0f0bSmrg 	return size_t(-1) / sizeof(value_type);
549*8feb0f0bSmrg #endif
550*8feb0f0bSmrg       }
5511debfc3dSmrg 
5521debfc3dSmrg       /**
5531debfc3dSmrg        *  @brief  Obtain an allocator to use when copying a container.
5541debfc3dSmrg        *  @param  __rhs  An allocator.
5551debfc3dSmrg        *  @return @c __rhs
5561debfc3dSmrg       */
557*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR allocator_type
5581debfc3dSmrg       select_on_container_copy_construction(const allocator_type& __rhs)
5591debfc3dSmrg       { return __rhs; }
5601debfc3dSmrg     };
5611debfc3dSmrg 
562*8feb0f0bSmrg   /// Explicit specialization for std::allocator<void>.
563*8feb0f0bSmrg   template<>
564*8feb0f0bSmrg     struct allocator_traits<allocator<void>>
565*8feb0f0bSmrg     {
566*8feb0f0bSmrg       /// The allocator type
567*8feb0f0bSmrg       using allocator_type = allocator<void>;
5681debfc3dSmrg 
569*8feb0f0bSmrg       /// The allocated type
570*8feb0f0bSmrg       using value_type = void;
571*8feb0f0bSmrg 
572*8feb0f0bSmrg       /// The allocator's pointer type.
573*8feb0f0bSmrg       using pointer = void*;
574*8feb0f0bSmrg 
575*8feb0f0bSmrg       /// The allocator's const pointer type.
576*8feb0f0bSmrg       using const_pointer = const void*;
577*8feb0f0bSmrg 
578*8feb0f0bSmrg       /// The allocator's void pointer type.
579*8feb0f0bSmrg       using void_pointer = void*;
580*8feb0f0bSmrg 
581*8feb0f0bSmrg       /// The allocator's const void pointer type.
582*8feb0f0bSmrg       using const_void_pointer = const void*;
583*8feb0f0bSmrg 
584*8feb0f0bSmrg       /// The allocator's difference type
585*8feb0f0bSmrg       using difference_type = std::ptrdiff_t;
586*8feb0f0bSmrg 
587*8feb0f0bSmrg       /// The allocator's size type
588*8feb0f0bSmrg       using size_type = std::size_t;
589*8feb0f0bSmrg 
590*8feb0f0bSmrg       /// How the allocator is propagated on copy assignment
591*8feb0f0bSmrg       using propagate_on_container_copy_assignment = false_type;
592*8feb0f0bSmrg 
593*8feb0f0bSmrg       /// How the allocator is propagated on move assignment
594*8feb0f0bSmrg       using propagate_on_container_move_assignment = true_type;
595*8feb0f0bSmrg 
596*8feb0f0bSmrg       /// How the allocator is propagated on swap
597*8feb0f0bSmrg       using propagate_on_container_swap = false_type;
598*8feb0f0bSmrg 
599*8feb0f0bSmrg       /// Whether all instances of the allocator type compare equal.
600*8feb0f0bSmrg       using is_always_equal = true_type;
601*8feb0f0bSmrg 
602*8feb0f0bSmrg       template<typename _Up>
603*8feb0f0bSmrg 	using rebind_alloc = allocator<_Up>;
604*8feb0f0bSmrg 
605*8feb0f0bSmrg       template<typename _Up>
606*8feb0f0bSmrg 	using rebind_traits = allocator_traits<allocator<_Up>>;
607*8feb0f0bSmrg 
608*8feb0f0bSmrg       /// allocate is ill-formed for allocator<void>
609*8feb0f0bSmrg       static void*
610*8feb0f0bSmrg       allocate(allocator_type&, size_type, const void* = nullptr) = delete;
611*8feb0f0bSmrg 
612*8feb0f0bSmrg       /// deallocate is ill-formed for allocator<void>
613*8feb0f0bSmrg       static void
614*8feb0f0bSmrg       deallocate(allocator_type&, void*, size_type) = delete;
615*8feb0f0bSmrg 
616*8feb0f0bSmrg       /**
617*8feb0f0bSmrg        *  @brief  Construct an object of type `_Up`
618*8feb0f0bSmrg        *  @param  __a  An allocator.
619*8feb0f0bSmrg        *  @param  __p  Pointer to memory of suitable size and alignment for
620*8feb0f0bSmrg        *	       an object of type `_Up`.
621*8feb0f0bSmrg        *  @param  __args Constructor arguments.
622*8feb0f0bSmrg        *
623*8feb0f0bSmrg        *  Calls `__a.construct(__p, std::forward<_Args>(__args)...)`
624*8feb0f0bSmrg        *  in C++11, C++14 and C++17. Changed in C++20 to call
625*8feb0f0bSmrg        *  `std::construct_at(__p, std::forward<_Args>(__args)...)` instead.
626*8feb0f0bSmrg       */
627*8feb0f0bSmrg       template<typename _Up, typename... _Args>
628*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR void
629*8feb0f0bSmrg 	construct(allocator_type&, _Up* __p, _Args&&... __args)
630*8feb0f0bSmrg 	noexcept(std::is_nothrow_constructible<_Up, _Args...>::value)
631*8feb0f0bSmrg 	{
632*8feb0f0bSmrg #if __cplusplus <= 201703L
633*8feb0f0bSmrg 	  ::new((void *)__p) _Up(std::forward<_Args>(__args)...);
634*8feb0f0bSmrg #else
635*8feb0f0bSmrg 	  std::construct_at(__p, std::forward<_Args>(__args)...);
636*8feb0f0bSmrg #endif
637*8feb0f0bSmrg 	}
638*8feb0f0bSmrg 
639*8feb0f0bSmrg       /**
640*8feb0f0bSmrg        *  @brief  Destroy an object of type `_Up`
641*8feb0f0bSmrg        *  @param  __a  An allocator.
642*8feb0f0bSmrg        *  @param  __p  Pointer to the object to destroy
643*8feb0f0bSmrg        *
644*8feb0f0bSmrg        *  Invokes the destructor for `*__p`.
645*8feb0f0bSmrg       */
646*8feb0f0bSmrg       template<typename _Up>
647*8feb0f0bSmrg 	static _GLIBCXX20_CONSTEXPR void
648*8feb0f0bSmrg 	destroy(allocator_type&, _Up* __p)
649*8feb0f0bSmrg 	noexcept(is_nothrow_destructible<_Up>::value)
650*8feb0f0bSmrg 	{ std::_Destroy(__p); }
651*8feb0f0bSmrg 
652*8feb0f0bSmrg       /// max_size is ill-formed for allocator<void>
653*8feb0f0bSmrg       static size_type
654*8feb0f0bSmrg       max_size(const allocator_type&) = delete;
655*8feb0f0bSmrg 
656*8feb0f0bSmrg       /**
657*8feb0f0bSmrg        *  @brief  Obtain an allocator to use when copying a container.
658*8feb0f0bSmrg        *  @param  __rhs  An allocator.
659*8feb0f0bSmrg        *  @return `__rhs`
660*8feb0f0bSmrg       */
661*8feb0f0bSmrg       static _GLIBCXX20_CONSTEXPR allocator_type
662*8feb0f0bSmrg       select_on_container_copy_construction(const allocator_type& __rhs)
663*8feb0f0bSmrg       { return __rhs; }
664*8feb0f0bSmrg     };
665*8feb0f0bSmrg 
666*8feb0f0bSmrg #if __cplusplus < 201703L
6671debfc3dSmrg   template<typename _Alloc>
6681debfc3dSmrg     inline void
6691debfc3dSmrg     __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type)
6701debfc3dSmrg     { __one = __two; }
6711debfc3dSmrg 
6721debfc3dSmrg   template<typename _Alloc>
6731debfc3dSmrg     inline void
6741debfc3dSmrg     __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type)
6751debfc3dSmrg     { }
676*8feb0f0bSmrg #endif
6771debfc3dSmrg 
6781debfc3dSmrg   template<typename _Alloc>
679*8feb0f0bSmrg     _GLIBCXX14_CONSTEXPR inline void
680*8feb0f0bSmrg     __alloc_on_copy(_Alloc& __one, const _Alloc& __two)
6811debfc3dSmrg     {
6821debfc3dSmrg       typedef allocator_traits<_Alloc> __traits;
6831debfc3dSmrg       typedef typename __traits::propagate_on_container_copy_assignment __pocca;
684*8feb0f0bSmrg #if __cplusplus >= 201703L
685*8feb0f0bSmrg       if constexpr (__pocca::value)
686*8feb0f0bSmrg 	__one = __two;
687*8feb0f0bSmrg #else
6881debfc3dSmrg       __do_alloc_on_copy(__one, __two, __pocca());
689*8feb0f0bSmrg #endif
6901debfc3dSmrg     }
6911debfc3dSmrg 
6921debfc3dSmrg   template<typename _Alloc>
693*8feb0f0bSmrg     constexpr _Alloc
694*8feb0f0bSmrg     __alloc_on_copy(const _Alloc& __a)
6951debfc3dSmrg     {
6961debfc3dSmrg       typedef allocator_traits<_Alloc> __traits;
6971debfc3dSmrg       return __traits::select_on_container_copy_construction(__a);
6981debfc3dSmrg     }
6991debfc3dSmrg 
700*8feb0f0bSmrg #if __cplusplus < 201703L
7011debfc3dSmrg   template<typename _Alloc>
7021debfc3dSmrg     inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type)
7031debfc3dSmrg     { __one = std::move(__two); }
7041debfc3dSmrg 
7051debfc3dSmrg   template<typename _Alloc>
7061debfc3dSmrg     inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type)
7071debfc3dSmrg     { }
708*8feb0f0bSmrg #endif
7091debfc3dSmrg 
7101debfc3dSmrg   template<typename _Alloc>
711*8feb0f0bSmrg     _GLIBCXX14_CONSTEXPR inline void
712*8feb0f0bSmrg     __alloc_on_move(_Alloc& __one, _Alloc& __two)
7131debfc3dSmrg     {
7141debfc3dSmrg       typedef allocator_traits<_Alloc> __traits;
7151debfc3dSmrg       typedef typename __traits::propagate_on_container_move_assignment __pocma;
716*8feb0f0bSmrg #if __cplusplus >= 201703L
717*8feb0f0bSmrg       if constexpr (__pocma::value)
718*8feb0f0bSmrg 	__one = std::move(__two);
719*8feb0f0bSmrg #else
7201debfc3dSmrg       __do_alloc_on_move(__one, __two, __pocma());
721*8feb0f0bSmrg #endif
7221debfc3dSmrg     }
7231debfc3dSmrg 
724*8feb0f0bSmrg #if __cplusplus < 201703L
7251debfc3dSmrg   template<typename _Alloc>
7261debfc3dSmrg     inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type)
7271debfc3dSmrg     {
7281debfc3dSmrg       using std::swap;
7291debfc3dSmrg       swap(__one, __two);
7301debfc3dSmrg     }
7311debfc3dSmrg 
7321debfc3dSmrg   template<typename _Alloc>
7331debfc3dSmrg     inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type)
7341debfc3dSmrg     { }
735*8feb0f0bSmrg #endif
7361debfc3dSmrg 
7371debfc3dSmrg   template<typename _Alloc>
738*8feb0f0bSmrg     _GLIBCXX14_CONSTEXPR inline void
739*8feb0f0bSmrg     __alloc_on_swap(_Alloc& __one, _Alloc& __two)
7401debfc3dSmrg     {
7411debfc3dSmrg       typedef allocator_traits<_Alloc> __traits;
7421debfc3dSmrg       typedef typename __traits::propagate_on_container_swap __pocs;
743*8feb0f0bSmrg #if __cplusplus >= 201703L
744*8feb0f0bSmrg       if constexpr (__pocs::value)
745*8feb0f0bSmrg 	{
746*8feb0f0bSmrg 	  using std::swap;
747*8feb0f0bSmrg 	  swap(__one, __two);
748*8feb0f0bSmrg 	}
749*8feb0f0bSmrg #else
7501debfc3dSmrg       __do_alloc_on_swap(__one, __two, __pocs());
751*8feb0f0bSmrg #endif
7521debfc3dSmrg     }
7531debfc3dSmrg 
754c0a68be4Smrg   template<typename _Alloc, typename _Tp,
755c0a68be4Smrg 	   typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
756c0a68be4Smrg 	   typename = void>
757c0a68be4Smrg     struct __is_alloc_insertable_impl
758c0a68be4Smrg     : false_type
759c0a68be4Smrg     { };
7601debfc3dSmrg 
761c0a68be4Smrg   template<typename _Alloc, typename _Tp, typename _ValueT>
762c0a68be4Smrg     struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
763c0a68be4Smrg       __void_t<decltype(allocator_traits<_Alloc>::construct(
764c0a68be4Smrg 		   std::declval<_Alloc&>(), std::declval<_ValueT*>(),
765c0a68be4Smrg 		   std::declval<_Tp>()))>>
766c0a68be4Smrg     : true_type
767c0a68be4Smrg     { };
7681debfc3dSmrg 
7691debfc3dSmrg   // true if _Alloc::value_type is CopyInsertable into containers using _Alloc
770c0a68be4Smrg   // (might be wrong if _Alloc::construct exists but is not constrained,
771c0a68be4Smrg   // i.e. actually trying to use it would still be invalid. Use with caution.)
7721debfc3dSmrg   template<typename _Alloc>
7731debfc3dSmrg     struct __is_copy_insertable
774c0a68be4Smrg     : __is_alloc_insertable_impl<_Alloc,
775c0a68be4Smrg 				 typename _Alloc::value_type const&>::type
7761debfc3dSmrg     { };
7771debfc3dSmrg 
7781debfc3dSmrg   // std::allocator<_Tp> just requires CopyConstructible
7791debfc3dSmrg   template<typename _Tp>
7801debfc3dSmrg     struct __is_copy_insertable<allocator<_Tp>>
7811debfc3dSmrg     : is_copy_constructible<_Tp>
7821debfc3dSmrg     { };
7831debfc3dSmrg 
784c0a68be4Smrg   // true if _Alloc::value_type is MoveInsertable into containers using _Alloc
785c0a68be4Smrg   // (might be wrong if _Alloc::construct exists but is not constrained,
786c0a68be4Smrg   // i.e. actually trying to use it would still be invalid. Use with caution.)
787c0a68be4Smrg   template<typename _Alloc>
788c0a68be4Smrg     struct __is_move_insertable
789c0a68be4Smrg     : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
790c0a68be4Smrg     { };
791c0a68be4Smrg 
792c0a68be4Smrg   // std::allocator<_Tp> just requires MoveConstructible
793c0a68be4Smrg   template<typename _Tp>
794c0a68be4Smrg     struct __is_move_insertable<allocator<_Tp>>
795c0a68be4Smrg     : is_move_constructible<_Tp>
796c0a68be4Smrg     { };
797c0a68be4Smrg 
798a2dc1f3fSmrg   // Trait to detect Allocator-like types.
799a2dc1f3fSmrg   template<typename _Alloc, typename = void>
800a2dc1f3fSmrg     struct __is_allocator : false_type { };
801a2dc1f3fSmrg 
802a2dc1f3fSmrg   template<typename _Alloc>
803a2dc1f3fSmrg     struct __is_allocator<_Alloc,
804a2dc1f3fSmrg       __void_t<typename _Alloc::value_type,
805a2dc1f3fSmrg 	       decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
806a2dc1f3fSmrg     : true_type { };
807a2dc1f3fSmrg 
808a2dc1f3fSmrg   template<typename _Alloc>
809a2dc1f3fSmrg     using _RequireAllocator
810a2dc1f3fSmrg       = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
811a2dc1f3fSmrg 
812c0a68be4Smrg   template<typename _Alloc>
813c0a68be4Smrg     using _RequireNotAllocator
814c0a68be4Smrg       = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
815*8feb0f0bSmrg #endif // C++11
816*8feb0f0bSmrg 
817*8feb0f0bSmrg   /**
818*8feb0f0bSmrg    * Destroy a range of objects using the supplied allocator.  For
819*8feb0f0bSmrg    * non-default allocators we do not optimize away invocation of
820*8feb0f0bSmrg    * destroy() even if _Tp has a trivial destructor.
821*8feb0f0bSmrg    */
822*8feb0f0bSmrg 
823*8feb0f0bSmrg   template<typename _ForwardIterator, typename _Allocator>
824*8feb0f0bSmrg     void
825*8feb0f0bSmrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
826*8feb0f0bSmrg 	     _Allocator& __alloc)
827*8feb0f0bSmrg     {
828*8feb0f0bSmrg       for (; __first != __last; ++__first)
829*8feb0f0bSmrg #if __cplusplus < 201103L
830*8feb0f0bSmrg 	__alloc.destroy(std::__addressof(*__first));
831*8feb0f0bSmrg #else
832*8feb0f0bSmrg 	allocator_traits<_Allocator>::destroy(__alloc,
833*8feb0f0bSmrg 					      std::__addressof(*__first));
834*8feb0f0bSmrg #endif
835*8feb0f0bSmrg     }
836*8feb0f0bSmrg 
837*8feb0f0bSmrg   template<typename _ForwardIterator, typename _Tp>
838*8feb0f0bSmrg     inline void
839*8feb0f0bSmrg     _Destroy(_ForwardIterator __first, _ForwardIterator __last,
840*8feb0f0bSmrg 	     allocator<_Tp>&)
841*8feb0f0bSmrg     {
842*8feb0f0bSmrg       _Destroy(__first, __last);
843*8feb0f0bSmrg     }
844c0a68be4Smrg 
8451debfc3dSmrg _GLIBCXX_END_NAMESPACE_VERSION
8461debfc3dSmrg } // namespace std
847a2dc1f3fSmrg #endif // _ALLOC_TRAITS_H
848