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