File indexing completed on 2026-05-03 08:13:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___MEMORY_ALLOCATOR_TRAITS_H
0011 #define _LIBCPP___CXX03___MEMORY_ALLOCATOR_TRAITS_H
0012
0013 #include <__cxx03/__config>
0014 #include <__cxx03/__memory/construct_at.h>
0015 #include <__cxx03/__memory/pointer_traits.h>
0016 #include <__cxx03/__type_traits/enable_if.h>
0017 #include <__cxx03/__type_traits/is_constructible.h>
0018 #include <__cxx03/__type_traits/is_empty.h>
0019 #include <__cxx03/__type_traits/is_same.h>
0020 #include <__cxx03/__type_traits/make_unsigned.h>
0021 #include <__cxx03/__type_traits/remove_reference.h>
0022 #include <__cxx03/__type_traits/void_t.h>
0023 #include <__cxx03/__utility/declval.h>
0024 #include <__cxx03/__utility/forward.h>
0025 #include <__cxx03/cstddef>
0026 #include <__cxx03/limits>
0027
0028 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0029 # pragma GCC system_header
0030 #endif
0031
0032 _LIBCPP_PUSH_MACROS
0033 #include <__cxx03/__undef_macros>
0034
0035 _LIBCPP_BEGIN_NAMESPACE_STD
0036
0037 #define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(NAME, PROPERTY) \
0038 template <class _Tp, class = void> \
0039 struct NAME : false_type {}; \
0040 template <class _Tp> \
0041 struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {}
0042
0043
0044 template <class _Tp,
0045 class _Alloc,
0046 class _RawAlloc = __libcpp_remove_reference_t<_Alloc>,
0047 bool = __has_pointer<_RawAlloc>::value>
0048 struct __pointer {
0049 using type _LIBCPP_NODEBUG = typename _RawAlloc::pointer;
0050 };
0051 template <class _Tp, class _Alloc, class _RawAlloc>
0052 struct __pointer<_Tp, _Alloc, _RawAlloc, false> {
0053 using type _LIBCPP_NODEBUG = _Tp*;
0054 };
0055
0056
0057 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_pointer, const_pointer);
0058 template <class _Tp, class _Ptr, class _Alloc, bool = __has_const_pointer<_Alloc>::value>
0059 struct __const_pointer {
0060 using type _LIBCPP_NODEBUG = typename _Alloc::const_pointer;
0061 };
0062 template <class _Tp, class _Ptr, class _Alloc>
0063 struct __const_pointer<_Tp, _Ptr, _Alloc, false> {
0064 #ifdef _LIBCPP_CXX03_LANG
0065 using type = typename pointer_traits<_Ptr>::template rebind<const _Tp>::other;
0066 #else
0067 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const _Tp>;
0068 #endif
0069 };
0070
0071
0072 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_void_pointer, void_pointer);
0073 template <class _Ptr, class _Alloc, bool = __has_void_pointer<_Alloc>::value>
0074 struct __void_pointer {
0075 using type _LIBCPP_NODEBUG = typename _Alloc::void_pointer;
0076 };
0077 template <class _Ptr, class _Alloc>
0078 struct __void_pointer<_Ptr, _Alloc, false> {
0079 #ifdef _LIBCPP_CXX03_LANG
0080 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<void>::other;
0081 #else
0082 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<void>;
0083 #endif
0084 };
0085
0086
0087 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_void_pointer, const_void_pointer);
0088 template <class _Ptr, class _Alloc, bool = __has_const_void_pointer<_Alloc>::value>
0089 struct __const_void_pointer {
0090 using type _LIBCPP_NODEBUG = typename _Alloc::const_void_pointer;
0091 };
0092 template <class _Ptr, class _Alloc>
0093 struct __const_void_pointer<_Ptr, _Alloc, false> {
0094 #ifdef _LIBCPP_CXX03_LANG
0095 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const void>::other;
0096 #else
0097 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const void>;
0098 #endif
0099 };
0100
0101
0102 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_size_type, size_type);
0103 template <class _Alloc, class _DiffType, bool = __has_size_type<_Alloc>::value>
0104 struct __size_type : make_unsigned<_DiffType> {};
0105 template <class _Alloc, class _DiffType>
0106 struct __size_type<_Alloc, _DiffType, true> {
0107 using type _LIBCPP_NODEBUG = typename _Alloc::size_type;
0108 };
0109
0110
0111 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_alloc_traits_difference_type, difference_type);
0112 template <class _Alloc, class _Ptr, bool = __has_alloc_traits_difference_type<_Alloc>::value>
0113 struct __alloc_traits_difference_type {
0114 using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::difference_type;
0115 };
0116 template <class _Alloc, class _Ptr>
0117 struct __alloc_traits_difference_type<_Alloc, _Ptr, true> {
0118 using type _LIBCPP_NODEBUG = typename _Alloc::difference_type;
0119 };
0120
0121
0122 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_copy_assignment, propagate_on_container_copy_assignment);
0123 template <class _Alloc, bool = __has_propagate_on_container_copy_assignment<_Alloc>::value>
0124 struct __propagate_on_container_copy_assignment : false_type {};
0125 template <class _Alloc>
0126 struct __propagate_on_container_copy_assignment<_Alloc, true> {
0127 using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_copy_assignment;
0128 };
0129
0130
0131 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_move_assignment, propagate_on_container_move_assignment);
0132 template <class _Alloc, bool = __has_propagate_on_container_move_assignment<_Alloc>::value>
0133 struct __propagate_on_container_move_assignment : false_type {};
0134 template <class _Alloc>
0135 struct __propagate_on_container_move_assignment<_Alloc, true> {
0136 using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_move_assignment;
0137 };
0138
0139
0140 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_swap, propagate_on_container_swap);
0141 template <class _Alloc, bool = __has_propagate_on_container_swap<_Alloc>::value>
0142 struct __propagate_on_container_swap : false_type {};
0143 template <class _Alloc>
0144 struct __propagate_on_container_swap<_Alloc, true> {
0145 using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_swap;
0146 };
0147
0148
0149 _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_is_always_equal, is_always_equal);
0150 template <class _Alloc, bool = __has_is_always_equal<_Alloc>::value>
0151 struct __is_always_equal : is_empty<_Alloc> {};
0152 template <class _Alloc>
0153 struct __is_always_equal<_Alloc, true> {
0154 using type _LIBCPP_NODEBUG = typename _Alloc::is_always_equal;
0155 };
0156
0157
0158 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0159 template <class _Tp, class _Up, class = void>
0160 struct __has_rebind_other : false_type {};
0161 template <class _Tp, class _Up>
0162 struct __has_rebind_other<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>::other> > : true_type {};
0163
0164 template <class _Tp, class _Up, bool = __has_rebind_other<_Tp, _Up>::value>
0165 struct __allocator_traits_rebind {
0166 static_assert(__has_rebind_other<_Tp, _Up>::value, "This allocator has to implement rebind");
0167 using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other;
0168 };
0169 template <template <class, class...> class _Alloc, class _Tp, class... _Args, class _Up>
0170 struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, true> {
0171 using type _LIBCPP_NODEBUG = typename _Alloc<_Tp, _Args...>::template rebind<_Up>::other;
0172 };
0173 template <template <class, class...> class _Alloc, class _Tp, class... _Args, class _Up>
0174 struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, false> {
0175 using type _LIBCPP_NODEBUG = _Alloc<_Up, _Args...>;
0176 };
0177 _LIBCPP_SUPPRESS_DEPRECATED_POP
0178
0179 template <class _Alloc, class _Tp>
0180 using __allocator_traits_rebind_t = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
0181
0182 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0183
0184
0185 template <class _Alloc, class _SizeType, class _ConstVoidPtr, class = void>
0186 struct __has_allocate_hint : false_type {};
0187
0188 template <class _Alloc, class _SizeType, class _ConstVoidPtr>
0189 struct __has_allocate_hint<
0190 _Alloc,
0191 _SizeType,
0192 _ConstVoidPtr,
0193 decltype((void)std::declval<_Alloc>().allocate(std::declval<_SizeType>(), std::declval<_ConstVoidPtr>()))>
0194 : true_type {};
0195
0196
0197 template <class, class _Alloc, class... _Args>
0198 struct __has_construct_impl : false_type {};
0199
0200 template <class _Alloc, class... _Args>
0201 struct __has_construct_impl<decltype((void)std::declval<_Alloc>().construct(std::declval<_Args>()...)),
0202 _Alloc,
0203 _Args...> : true_type {};
0204
0205 template <class _Alloc, class... _Args>
0206 struct __has_construct : __has_construct_impl<void, _Alloc, _Args...> {};
0207
0208
0209 template <class _Alloc, class _Pointer, class = void>
0210 struct __has_destroy : false_type {};
0211
0212 template <class _Alloc, class _Pointer>
0213 struct __has_destroy<_Alloc, _Pointer, decltype((void)std::declval<_Alloc>().destroy(std::declval<_Pointer>()))>
0214 : true_type {};
0215
0216
0217 template <class _Alloc, class = void>
0218 struct __has_max_size : false_type {};
0219
0220 template <class _Alloc>
0221 struct __has_max_size<_Alloc, decltype((void)std::declval<_Alloc&>().max_size())> : true_type {};
0222
0223
0224 template <class _Alloc, class = void>
0225 struct __has_select_on_container_copy_construction : false_type {};
0226
0227 template <class _Alloc>
0228 struct __has_select_on_container_copy_construction<
0229 _Alloc,
0230 decltype((void)std::declval<_Alloc>().select_on_container_copy_construction())> : true_type {};
0231
0232 _LIBCPP_SUPPRESS_DEPRECATED_POP
0233
0234 #if _LIBCPP_STD_VER >= 23
0235
0236 template <class _Pointer, class _SizeType = size_t>
0237 struct allocation_result {
0238 _Pointer ptr;
0239 _SizeType count;
0240 };
0241 _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);
0242
0243 #endif
0244
0245 template <class _Alloc>
0246 struct _LIBCPP_TEMPLATE_VIS allocator_traits {
0247 using allocator_type = _Alloc;
0248 using value_type = typename allocator_type::value_type;
0249 using pointer = typename __pointer<value_type, allocator_type>::type;
0250 using const_pointer = typename __const_pointer<value_type, pointer, allocator_type>::type;
0251 using void_pointer = typename __void_pointer<pointer, allocator_type>::type;
0252 using const_void_pointer = typename __const_void_pointer<pointer, allocator_type>::type;
0253 using difference_type = typename __alloc_traits_difference_type<allocator_type, pointer>::type;
0254 using size_type = typename __size_type<allocator_type, difference_type>::type;
0255 using propagate_on_container_copy_assignment =
0256 typename __propagate_on_container_copy_assignment<allocator_type>::type;
0257 using propagate_on_container_move_assignment =
0258 typename __propagate_on_container_move_assignment<allocator_type>::type;
0259 using propagate_on_container_swap = typename __propagate_on_container_swap<allocator_type>::type;
0260 using is_always_equal = typename __is_always_equal<allocator_type>::type;
0261
0262 #ifndef _LIBCPP_CXX03_LANG
0263 template <class _Tp>
0264 using rebind_alloc = __allocator_traits_rebind_t<allocator_type, _Tp>;
0265 template <class _Tp>
0266 using rebind_traits = allocator_traits<rebind_alloc<_Tp> >;
0267 #else
0268 template <class _Tp>
0269 struct rebind_alloc {
0270 using other = __allocator_traits_rebind_t<allocator_type, _Tp>;
0271 };
0272 template <class _Tp>
0273 struct rebind_traits {
0274 using other = allocator_traits<typename rebind_alloc<_Tp>::other>;
0275 };
0276 #endif
0277
0278 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
0279 allocate(allocator_type& __a, size_type __n) {
0280 return __a.allocate(__n);
0281 }
0282
0283 template <class _Ap = _Alloc, __enable_if_t<__has_allocate_hint<_Ap, size_type, const_void_pointer>::value, int> = 0>
0284 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
0285 allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) {
0286 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0287 return __a.allocate(__n, __hint);
0288 _LIBCPP_SUPPRESS_DEPRECATED_POP
0289 }
0290 template <class _Ap = _Alloc,
0291 class = void,
0292 __enable_if_t<!__has_allocate_hint<_Ap, size_type, const_void_pointer>::value, int> = 0>
0293 _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
0294 allocate(allocator_type& __a, size_type __n, const_void_pointer) {
0295 return __a.allocate(__n);
0296 }
0297
0298 #if _LIBCPP_STD_VER >= 23
0299 template <class _Ap = _Alloc>
0300 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr allocation_result<pointer, size_type>
0301 allocate_at_least(_Ap& __alloc, size_type __n) {
0302 if constexpr (requires { __alloc.allocate_at_least(__n); }) {
0303 return __alloc.allocate_at_least(__n);
0304 } else {
0305 return {__alloc.allocate(__n), __n};
0306 }
0307 }
0308 #endif
0309
0310 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
0311 deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT {
0312 __a.deallocate(__p, __n);
0313 }
0314
0315 template <class _Tp, class... _Args, __enable_if_t<__has_construct<allocator_type, _Tp*, _Args...>::value, int> = 0>
0316 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
0317 construct(allocator_type& __a, _Tp* __p, _Args&&... __args) {
0318 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0319 __a.construct(__p, std::forward<_Args>(__args)...);
0320 _LIBCPP_SUPPRESS_DEPRECATED_POP
0321 }
0322 template <class _Tp,
0323 class... _Args,
0324 class = void,
0325 __enable_if_t<!__has_construct<allocator_type, _Tp*, _Args...>::value, int> = 0>
0326 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void
0327 construct(allocator_type&, _Tp* __p, _Args&&... __args) {
0328 std::__construct_at(__p, std::forward<_Args>(__args)...);
0329 }
0330
0331 template <class _Tp, __enable_if_t<__has_destroy<allocator_type, _Tp*>::value, int> = 0>
0332 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type& __a, _Tp* __p) {
0333 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0334 __a.destroy(__p);
0335 _LIBCPP_SUPPRESS_DEPRECATED_POP
0336 }
0337 template <class _Tp, class = void, __enable_if_t<!__has_destroy<allocator_type, _Tp*>::value, int> = 0>
0338 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type&, _Tp* __p) {
0339 std::__destroy_at(__p);
0340 }
0341
0342 template <class _Ap = _Alloc, __enable_if_t<__has_max_size<const _Ap>::value, int> = 0>
0343 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type& __a) _NOEXCEPT {
0344 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
0345 return __a.max_size();
0346 _LIBCPP_SUPPRESS_DEPRECATED_POP
0347 }
0348 template <class _Ap = _Alloc, class = void, __enable_if_t<!__has_max_size<const _Ap>::value, int> = 0>
0349 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type&) _NOEXCEPT {
0350 return numeric_limits<size_type>::max() / sizeof(value_type);
0351 }
0352
0353 template <class _Ap = _Alloc, __enable_if_t<__has_select_on_container_copy_construction<const _Ap>::value, int> = 0>
0354 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
0355 select_on_container_copy_construction(const allocator_type& __a) {
0356 return __a.select_on_container_copy_construction();
0357 }
0358 template <class _Ap = _Alloc,
0359 class = void,
0360 __enable_if_t<!__has_select_on_container_copy_construction<const _Ap>::value, int> = 0>
0361 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type
0362 select_on_container_copy_construction(const allocator_type& __a) {
0363 return __a;
0364 }
0365 };
0366
0367 #ifndef _LIBCPP_CXX03_LANG
0368 template <class _Traits, class _Tp>
0369 using __rebind_alloc _LIBCPP_NODEBUG = typename _Traits::template rebind_alloc<_Tp>;
0370 #else
0371 template <class _Traits, class _Tp>
0372 using __rebind_alloc = typename _Traits::template rebind_alloc<_Tp>::other;
0373 #endif
0374
0375 template <class _Alloc>
0376 struct __check_valid_allocator : true_type {
0377 using _Traits = std::allocator_traits<_Alloc>;
0378 static_assert(is_same<_Alloc, __rebind_alloc<_Traits, typename _Traits::value_type> >::value,
0379 "[allocator.requirements] states that rebinding an allocator to the same type should result in the "
0380 "original allocator");
0381 };
0382
0383
0384 template <class _Tp>
0385 struct __is_default_allocator : false_type {};
0386
0387 template <class>
0388 class allocator;
0389
0390 template <class _Tp>
0391 struct __is_default_allocator<allocator<_Tp> > : true_type {};
0392
0393
0394 template <class _Alloc, class = void>
0395 struct __is_cpp17_move_insertable : is_move_constructible<typename _Alloc::value_type> {};
0396
0397 template <class _Alloc>
0398 struct __is_cpp17_move_insertable<
0399 _Alloc,
0400 __enable_if_t< !__is_default_allocator<_Alloc>::value &&
0401 __has_construct<_Alloc, typename _Alloc::value_type*, typename _Alloc::value_type&&>::value > >
0402 : true_type {};
0403
0404
0405 template <class _Alloc, class = void>
0406 struct __is_cpp17_copy_insertable
0407 : integral_constant<bool,
0408 is_copy_constructible<typename _Alloc::value_type>::value &&
0409 __is_cpp17_move_insertable<_Alloc>::value > {};
0410
0411 template <class _Alloc>
0412 struct __is_cpp17_copy_insertable<
0413 _Alloc,
0414 __enable_if_t< !__is_default_allocator<_Alloc>::value &&
0415 __has_construct<_Alloc, typename _Alloc::value_type*, const typename _Alloc::value_type&>::value > >
0416 : __is_cpp17_move_insertable<_Alloc> {};
0417
0418 #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX
0419
0420 _LIBCPP_END_NAMESPACE_STD
0421
0422 _LIBCPP_POP_MACROS
0423
0424 #endif