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