30 #ifndef _ALLOC_TRAITS_H
31 #define _ALLOC_TRAITS_H 1
35 #if __cplusplus >= 201103L
46 namespace std _GLIBCXX_VISIBILITY(default)
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 #if __cplusplus >= 201103L
52 #pragma GCC diagnostic push
53 #pragma GCC diagnostic ignored "-Wc++14-extensions" // for variable templates
54 #pragma GCC diagnostic ignored "-Wc++17-extensions" // for if-constexpr
57 struct __allocator_traits_base
60 template<
typename _Tp,
typename _Up>
62 template<
typename _Tp,
typename _Up,
typename =
void>
64 struct __rebind : __replace_first_arg<_Tp, _Up>
66 static_assert(is_same<
67 typename __replace_first_arg<_Tp, typename _Tp::value_type>::type,
69 "allocator_traits<A>::rebind_alloc<A::value_type> must be A");
72 template<
typename _Tp,
typename _Up>
74 requires requires {
typename _Tp::template rebind<_Up>::other; }
75 struct __rebind<_Tp, _Up>
77 struct __rebind<_Tp, _Up,
78 __void_t<typename _Tp::template rebind<_Up>::other>>
81 using type =
typename _Tp::template rebind<_Up>::other;
83 static_assert(is_same<
84 typename _Tp::template rebind<typename _Tp::value_type>::other,
86 "allocator_traits<A>::rebind_alloc<A::value_type> must be A");
90 template<
typename _Tp>
91 using __pointer =
typename _Tp::pointer;
92 template<
typename _Tp>
93 using __c_pointer =
typename _Tp::const_pointer;
94 template<
typename _Tp>
95 using __v_pointer =
typename _Tp::void_pointer;
96 template<
typename _Tp>
97 using __cv_pointer =
typename _Tp::const_void_pointer;
98 template<
typename _Tp>
99 using __pocca =
typename _Tp::propagate_on_container_copy_assignment;
100 template<
typename _Tp>
101 using __pocma =
typename _Tp::propagate_on_container_move_assignment;
102 template<
typename _Tp>
103 using __pocs =
typename _Tp::propagate_on_container_swap;
104 template<
typename _Tp>
105 using __equal = __type_identity<typename _Tp::is_always_equal>;
109 template<
typename _Alloc,
typename _Sz,
typename _Vp>
110 static constexpr
bool __has_allocate_hint
111 = requires (_Alloc& __a, _Sz __n, _Vp __hint) {
112 __a.allocate(__n, __hint);
115 template<
typename _Alloc,
typename _Sz,
typename _Vp>
116 using __allocate_hint_t
117 = decltype(std::declval<_Alloc&>()
118 .allocate(std::declval<_Sz>(), std::declval<_Vp>()));
119 template<
typename _Alloc,
typename _Sz,
typename _Vp,
typename =
void>
120 static constexpr
bool __has_allocate_hint =
false;
121 template<
typename _Alloc,
typename _Sz,
typename _Vp>
122 static constexpr
bool
123 __has_allocate_hint<_Alloc, _Sz, _Vp,
124 __void_t<__allocate_hint_t<_Alloc, _Sz, _Vp>>>
133 template<
typename _Alloc,
typename _Tp,
typename... _Args>
134 static constexpr
bool __has_construct
135 = requires (_Alloc& __a, _Tp* __p, _Args&&... __args) {
136 __a.construct(__p, std::forward<_Args>(__args)...);
138 template<
typename _Tp,
typename... _Args>
139 static constexpr
bool __can_construct_at
140 = requires (_Tp* __p, _Args&&... __args) {
141 #if __cpp_constexpr_dynamic_alloc
142 std::construct_at(__p, std::forward<_Args>(__args)...);
144 ::new((
void*)__p) _Tp(std::forward<_Args>(__args)...);
147 template<
typename _Alloc,
typename _Tp,
typename... _Args>
148 static constexpr
bool __can_construct
149 = __has_construct<_Alloc, _Tp, _Args...>
150 || __can_construct_at<_Tp, _Args...>;
152 template<
typename _Alloc,
typename _Tp,
typename... _Args>
154 = decltype(std::declval<_Alloc&>().construct(std::declval<_Tp*>(),
155 std::declval<_Args>()...));
156 template<
typename _Alloc,
typename _Tp,
typename,
typename... _Args>
157 static constexpr
bool __has_construct_impl =
false;
158 template<
typename _Alloc,
typename _Tp,
typename... _Args>
159 static constexpr
bool
160 __has_construct_impl<_Alloc, _Tp,
161 __void_t<__construct_t<_Alloc, _Tp, _Args...>>,
164 template<
typename _Alloc,
typename _Tp,
typename... _Args>
165 static constexpr
bool __has_construct
166 = __has_construct_impl<_Alloc, _Tp, void, _Args...>;
167 template<
typename _Tp,
typename... _Args>
169 = decltype(::
new((
void*)0) _Tp(std::declval<_Args>()...));
170 template<
typename _Tp,
typename,
typename... _Args>
171 static constexpr
bool __has_new_expr =
false;
172 template<
typename _Tp,
typename... _Args>
173 static constexpr
bool
174 __has_new_expr<_Tp, __void_t<__new_expr_t<_Tp, _Args...>>, _Args...>
176 template<
typename _Alloc,
typename _Tp,
typename... _Args>
177 static constexpr
bool __can_construct
178 = __has_construct<_Alloc, _Tp, _Args...>
179 || __has_new_expr<_Tp, void, _Args...>;
184 template<
typename _Alloc,
typename _Tp>
185 static constexpr
bool __has_destroy = requires (_Alloc& __a, _Tp* __p) {
189 template<
typename _Alloc,
typename _Tp>
191 = decltype(std::declval<_Alloc&>().destroy(std::declval<_Tp*>()));
192 template<
typename _Alloc,
typename _Tp,
typename =
void>
193 static constexpr
bool __has_destroy =
false;
194 template<
typename _Alloc,
typename _Tp>
195 static constexpr
bool __has_destroy<_Alloc, _Tp,
196 __void_t<__destroy_t<_Alloc, _Tp>>>
202 template<
typename _Alloc>
203 static constexpr
bool __has_max_size = requires (
const _Alloc& __a) {
207 template<
typename _Alloc>
208 using __max_size_t = decltype(std::declval<const _Alloc&>().max_size());
209 template<
typename _Alloc,
typename =
void>
210 static constexpr
bool __has_max_size =
false;
211 template<
typename _Alloc>
212 static constexpr
bool __has_max_size<_Alloc,
213 __void_t<__max_size_t<_Alloc>>>
220 template<
typename _Alloc>
221 static constexpr
bool __has_soccc = requires (
const _Alloc& __a) {
222 __a.select_on_container_copy_construction();
225 template<
typename _Alloc>
227 = decltype(std::declval<const _Alloc&>()
228 .select_on_container_copy_construction());
229 template<
typename _Alloc,
typename =
void>
230 static constexpr
bool __has_soccc =
false;
231 template<
typename _Alloc>
232 static constexpr
bool __has_soccc<_Alloc, __void_t<__soccc_t<_Alloc>>>
237 template<
typename _Alloc,
typename _Up>
239 =
typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
248 template<
typename _Alloc>
261 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>;
265 template<
template<
typename>
class _Func,
typename _Tp,
typename =
void>
271 template<
template<
typename>
class _Func,
typename _Tp>
272 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>>
274 using type = _Func<_Alloc>;
278 template<
typename _A2,
typename _PtrT,
typename =
void>
280 {
using type =
typename pointer_traits<_PtrT>::difference_type; };
282 template<
typename _A2,
typename _PtrT>
284 {
using type =
typename _A2::difference_type; };
287 template<
typename _A2,
typename _DiffT,
typename =
void>
288 struct _Size : make_unsigned<_DiffT> { };
290 template<
typename _A2,
typename _DiffT>
291 struct _Size<_A2, _DiffT, __void_t<typename _A2::
size_type>>
292 {
using type =
typename _A2::size_type; };
333 using size_type =
typename _Size<_Alloc, difference_type>::type;
342 = __detected_or_t<false_type, __pocca, _Alloc>;
351 = __detected_or_t<false_type, __pocma, _Alloc>;
360 = __detected_or_t<false_type, __pocs, _Alloc>;
369 =
typename __detected_or_t<is_empty<_Alloc>, __equal, _Alloc>::type;
371 template<
typename _Tp>
372 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>;
373 template<
typename _Tp>
383 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR
pointer
385 {
return __a.allocate(__n); }
398 _GLIBCXX_NODISCARD
static _GLIBCXX20_CONSTEXPR
pointer
401 if constexpr (__has_allocate_hint<_Alloc, size_type, const_void_pointer>)
402 return __a.allocate(__n, __hint);
404 return __a.allocate(__n);
407 #ifdef __glibcxx_allocate_at_least // C++23
420 [[nodiscard]]
static constexpr
auto
421 allocate_at_least(_Alloc& __a,
size_type __n)
422 -> allocation_result<pointer, size_type>
424 if constexpr (requires { __a.allocate_at_least(__n); })
425 return __a.allocate_at_least(__n);
427 return { __a.allocate(__n), __n };
439 static _GLIBCXX20_CONSTEXPR
void
441 { __a.deallocate(__p, __n); }
454 template<
typename _Tp,
typename... _Args>
455 #if __cpp_concepts && __cpp_constexpr_dynamic_alloc
456 requires __can_construct<_Alloc, _Tp, _Args...>
457 static constexpr
void
459 static __enable_if_t<__can_construct<_Alloc, _Tp, _Args...>>
462 noexcept(_S_nothrow_construct<_Tp, _Args...>())
464 if constexpr (__has_construct<_Alloc, _Tp, _Args...>)
465 __a.construct(__p, std::forward<_Args>(__args)...);
478 template<
typename _Tp>
479 static _GLIBCXX20_CONSTEXPR
void
481 noexcept(_S_nothrow_destroy<_Tp>())
483 if constexpr (__has_destroy<_Alloc, _Tp>)
500 if constexpr (__has_max_size<_Alloc>)
501 return __a.max_size();
505 return __gnu_cxx::__numeric_traits<size_type>::__max
517 static _GLIBCXX20_CONSTEXPR _Alloc
520 if constexpr (__has_soccc<_Alloc>)
521 return __rhs.select_on_container_copy_construction();
527 #if __cpp_constexpr >= 201304 // >= C++14
528 template<
typename _Tp,
typename... _Args>
529 static constexpr
bool
530 _S_nothrow_construct(_Alloc* __a =
nullptr, _Tp* __p =
nullptr)
532 if constexpr (__has_construct<_Alloc, _Tp, _Args...>)
533 return noexcept(__a->construct(__p, std::declval<_Args>()...));
535 return __is_nothrow_new_constructible<_Tp, _Args...>;
538 template<
typename _Tp>
539 static constexpr
bool
540 _S_nothrow_destroy(_Alloc* __a =
nullptr, _Tp* __p =
nullptr)
542 if constexpr (__has_destroy<_Alloc, _Tp>)
543 return noexcept(__a->destroy(__p));
545 return is_nothrow_destructible<_Tp>::value;
548 template<
typename _Tp,
typename... _Args>
550 __enable_if_t<__has_construct<_Alloc, _Tp, _Args...>,
bool>
551 _S_nothrow_construct(_Alloc* __a =
nullptr, _Tp* __p =
nullptr)
552 {
return noexcept(__a->construct(__p, std::declval<_Args>()...)); }
554 template<
typename _Tp,
typename... _Args>
556 __enable_if_t<!__has_construct<_Alloc, _Tp, _Args...>,
bool>
557 _S_nothrow_construct(_Alloc* =
nullptr, _Tp* __p =
nullptr)
558 {
return __is_nothrow_new_constructible<_Tp, _Args...>; }
560 template<
typename _Tp>
562 __enable_if_t<__has_destroy<_Alloc, _Tp>,
bool>
563 _S_nothrow_destroy(_Alloc* __a =
nullptr, _Tp* __p =
nullptr)
564 {
return noexcept(__a->destroy(__p)); }
566 template<
typename _Tp>
568 __enable_if_t<!__has_destroy<_Alloc, _Tp>,
bool>
569 _S_nothrow_destroy(_Alloc* =
nullptr, _Tp* __p =
nullptr)
570 {
return is_nothrow_destructible<_Tp>::value; }
573 #pragma GCC diagnostic pop
583 template<
typename _Tp>
622 template<
typename _Up>
625 template<
typename _Up>
635 [[__nodiscard__,__gnu__::__always_inline__]]
636 static _GLIBCXX20_CONSTEXPR
pointer
638 {
return __a.allocate(__n); }
650 [[__nodiscard__,__gnu__::__always_inline__]]
651 static _GLIBCXX20_CONSTEXPR
pointer
655 #if __cplusplus <= 201703L
656 return __a.allocate(__n, __hint);
658 return __a.allocate(__n);
662 #ifdef __glibcxx_allocate_at_least // C++23
672 [[nodiscard]]
static constexpr
auto
674 -> allocation_result<pointer, size_type>
675 {
return __a.allocate_at_least(__n); }
686 [[__gnu__::__always_inline__]]
687 static _GLIBCXX20_CONSTEXPR
void
689 { __a.deallocate(__p, __n); }
702 template<
typename _Up,
typename... _Args>
703 [[__gnu__::__always_inline__]]
704 static _GLIBCXX20_CONSTEXPR
void
706 _Up* __p, _Args&&... __args)
707 #if __cplusplus <= 201703L
708 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...)))
710 noexcept(__is_nothrow_new_constructible<_Up, _Args...>)
713 #if __cplusplus <= 201703L
714 __a.construct(__p, std::forward<_Args>(__args)...);
715 #elif __cpp_constexpr_dynamic_alloc // >= C++20
716 std::construct_at(__p, std::forward<_Args>(__args)...);
729 template<
typename _Up>
730 [[__gnu__::__always_inline__]]
731 static _GLIBCXX20_CONSTEXPR
void
735 #if __cplusplus <= 201703L
738 std::destroy_at(__p);
747 [[__gnu__::__always_inline__]]
751 #if __cplusplus <= 201703L
752 return __a.max_size();
763 [[__gnu__::__always_inline__]]
815 template<
typename _Up>
818 template<
typename _Up>
840 template<
typename _Up,
typename... _Args>
841 [[__gnu__::__always_inline__]]
842 static _GLIBCXX20_CONSTEXPR
void
844 noexcept(__is_nothrow_new_constructible<_Up, _Args...>)
854 template<
typename _Up>
855 [[__gnu__::__always_inline__]]
856 static _GLIBCXX20_CONSTEXPR
void
870 [[__gnu__::__always_inline__]]
878 #pragma GCC diagnostic push
879 #pragma GCC diagnostic ignored "-Wc++17-extensions" // if constexpr
880 template<
typename _Alloc>
881 [[__gnu__::__always_inline__]]
882 _GLIBCXX14_CONSTEXPR
inline void
883 __alloc_on_copy(_Alloc& __one,
const _Alloc& __two)
885 using __traits = allocator_traits<_Alloc>;
887 typename __traits::propagate_on_container_copy_assignment::type;
888 if constexpr (__pocca::value)
892 template<
typename _Alloc>
893 [[__gnu__::__always_inline__]]
895 __alloc_on_copy(
const _Alloc& __a)
897 typedef allocator_traits<_Alloc> __traits;
898 return __traits::select_on_container_copy_construction(__a);
901 template<
typename _Alloc>
902 [[__gnu__::__always_inline__]]
903 _GLIBCXX14_CONSTEXPR
inline void
904 __alloc_on_move(_Alloc& __one, _Alloc& __two)
906 using __traits = allocator_traits<_Alloc>;
908 =
typename __traits::propagate_on_container_move_assignment::type;
909 if constexpr (__pocma::value)
913 template<
typename _Alloc>
914 [[__gnu__::__always_inline__]]
915 _GLIBCXX14_CONSTEXPR
inline void
916 __alloc_on_swap(_Alloc& __one, _Alloc& __two)
918 using __traits = allocator_traits<_Alloc>;
919 using __pocs =
typename __traits::propagate_on_container_swap::type;
920 if constexpr (__pocs::value)
926 #pragma GCC diagnostic pop
928 template<
typename _Alloc,
typename _Tp,
929 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>,
931 struct __is_alloc_insertable_impl
935 template<
typename _Alloc,
typename _Tp,
typename _ValueT>
936 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT,
937 __void_t<decltype(allocator_traits<_Alloc>::construct(
938 std::declval<_Alloc&>(), std::declval<_ValueT*>(),
939 std::declval<_Tp>()))>>
946 template<
typename _Alloc>
947 struct __is_copy_insertable
948 : __is_alloc_insertable_impl<_Alloc,
949 typename _Alloc::value_type const&>::type
954 template<
typename _Tp>
955 struct __is_copy_insertable<allocator<_Tp>>
956 : is_copy_constructible<_Tp>
963 template<
typename _Alloc>
964 struct __is_move_insertable
965 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type
970 template<
typename _Tp>
971 struct __is_move_insertable<allocator<_Tp>>
972 : is_move_constructible<_Tp>
977 template<
typename _Alloc,
typename =
void>
980 template<
typename _Alloc>
981 struct __is_allocator<_Alloc,
982 __void_t<typename _Alloc::value_type,
983 decltype(std::declval<_Alloc&>().allocate(size_t{}))>>
986 template<
typename _Alloc>
987 using _RequireAllocator
988 =
typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type;
990 template<
typename _Alloc>
991 using _RequireNotAllocator
992 =
typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type;
994 #if __cpp_concepts >= 201907L
995 template<
typename _Alloc>
996 concept __allocator_like = requires (_Alloc& __a) {
997 typename _Alloc::value_type;
998 __a.deallocate(__a.allocate(1u), 1u);
1001 template<
typename _Alloc>
1002 concept __not_allocator_like = !__allocator_like<_Alloc>;
1010 template<
typename _Alloc,
bool = __is_empty(_Alloc)>
1012 {
static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } };
1014 template<
typename _Alloc>
1015 struct __alloc_swap<_Alloc, false>
1018 _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT
1026 #if __cplusplus >= 201103L
1027 template<
typename _Tp,
bool
1028 = __or_<is_copy_constructible<typename _Tp::value_type>,
1029 is_nothrow_move_constructible<typename _Tp::value_type>>::value>
1030 struct __shrink_to_fit_aux
1031 {
static bool _S_do_it(_Tp&) noexcept {
return false; } };
1033 template<
typename _Tp>
1034 struct __shrink_to_fit_aux<_Tp, true>
1036 _GLIBCXX20_CONSTEXPR
1038 _S_do_it(_Tp& __c) noexcept
1040 #if __cpp_exceptions
1043 _Tp(__make_move_if_noexcept_iterator(__c.begin()),
1044 __make_move_if_noexcept_iterator(__c.end()),
1045 __c.get_allocator()).swap(__c);
1063 template<
typename _ForwardIterator,
typename _Allocator>
1064 _GLIBCXX20_CONSTEXPR
1066 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
1067 _Allocator& __alloc)
1069 for (; __first != __last; ++__first)
1070 #
if __cplusplus < 201103L
1079 template<
typename _ForwardIterator,
typename _Tp>
1080 __attribute__((__always_inline__)) _GLIBCXX20_CONSTEXPR
1082 _Destroy(_ForwardIterator __first, _ForwardIterator __last,
1091 _GLIBCXX_END_NAMESPACE_VERSION
1093 #endif // _ALLOC_TRAITS_H