1e8d8bef9SDimitry Andric // -*- C++ -*- 2e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 3e8d8bef9SDimitry Andric // 4e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 6e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7e8d8bef9SDimitry Andric // 8e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 9e8d8bef9SDimitry Andric 10e8d8bef9SDimitry Andric #ifndef _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H 11e8d8bef9SDimitry Andric #define _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H 12e8d8bef9SDimitry Andric 13e8d8bef9SDimitry Andric #include <__config> 14fe6060f1SDimitry Andric #include <__memory/construct_at.h> 15e8d8bef9SDimitry Andric #include <__memory/pointer_traits.h> 16bdd1243dSDimitry Andric #include <__type_traits/enable_if.h> 17*0fca6ea1SDimitry Andric #include <__type_traits/is_constructible.h> 18bdd1243dSDimitry Andric #include <__type_traits/is_empty.h> 19*0fca6ea1SDimitry Andric #include <__type_traits/is_same.h> 20bdd1243dSDimitry Andric #include <__type_traits/make_unsigned.h> 21bdd1243dSDimitry Andric #include <__type_traits/remove_reference.h> 22bdd1243dSDimitry Andric #include <__type_traits/void_t.h> 23bdd1243dSDimitry Andric #include <__utility/declval.h> 24fe6060f1SDimitry Andric #include <__utility/forward.h> 25*0fca6ea1SDimitry Andric #include <cstddef> 26fe6060f1SDimitry Andric #include <limits> 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 29e8d8bef9SDimitry Andric # pragma GCC system_header 30e8d8bef9SDimitry Andric #endif 31e8d8bef9SDimitry Andric 32e8d8bef9SDimitry Andric _LIBCPP_PUSH_MACROS 33e8d8bef9SDimitry Andric #include <__undef_macros> 34e8d8bef9SDimitry Andric 35e8d8bef9SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 36e8d8bef9SDimitry Andric 37e8d8bef9SDimitry Andric #define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(NAME, PROPERTY) \ 38cb14a3feSDimitry Andric template <class _Tp, class = void> \ 39cb14a3feSDimitry Andric struct NAME : false_type {}; \ 40cb14a3feSDimitry Andric template <class _Tp> \ 41cb14a3feSDimitry Andric struct NAME<_Tp, __void_t<typename _Tp::PROPERTY > > : true_type {} 42e8d8bef9SDimitry Andric 43e8d8bef9SDimitry Andric // __pointer 44cb14a3feSDimitry Andric template <class _Tp, 45cb14a3feSDimitry Andric class _Alloc, 46bdd1243dSDimitry Andric class _RawAlloc = __libcpp_remove_reference_t<_Alloc>, 47e8d8bef9SDimitry Andric bool = __has_pointer<_RawAlloc>::value> 48e8d8bef9SDimitry Andric struct __pointer { 49349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _RawAlloc::pointer; 50e8d8bef9SDimitry Andric }; 51e8d8bef9SDimitry Andric template <class _Tp, class _Alloc, class _RawAlloc> 52e8d8bef9SDimitry Andric struct __pointer<_Tp, _Alloc, _RawAlloc, false> { 53349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = _Tp*; 54e8d8bef9SDimitry Andric }; 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric // __const_pointer 57e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_pointer, const_pointer); 58cb14a3feSDimitry Andric template <class _Tp, class _Ptr, class _Alloc, bool = __has_const_pointer<_Alloc>::value> 59e8d8bef9SDimitry Andric struct __const_pointer { 60349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::const_pointer; 61e8d8bef9SDimitry Andric }; 62e8d8bef9SDimitry Andric template <class _Tp, class _Ptr, class _Alloc> 63e8d8bef9SDimitry Andric struct __const_pointer<_Tp, _Ptr, _Alloc, false> { 64e8d8bef9SDimitry Andric #ifdef _LIBCPP_CXX03_LANG 65e8d8bef9SDimitry Andric using type = typename pointer_traits<_Ptr>::template rebind<const _Tp>::other; 66e8d8bef9SDimitry Andric #else 67349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const _Tp>; 68e8d8bef9SDimitry Andric #endif 69e8d8bef9SDimitry Andric }; 70e8d8bef9SDimitry Andric 71e8d8bef9SDimitry Andric // __void_pointer 72e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_void_pointer, void_pointer); 73cb14a3feSDimitry Andric template <class _Ptr, class _Alloc, bool = __has_void_pointer<_Alloc>::value> 74e8d8bef9SDimitry Andric struct __void_pointer { 75349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::void_pointer; 76e8d8bef9SDimitry Andric }; 77e8d8bef9SDimitry Andric template <class _Ptr, class _Alloc> 78e8d8bef9SDimitry Andric struct __void_pointer<_Ptr, _Alloc, false> { 79e8d8bef9SDimitry Andric #ifdef _LIBCPP_CXX03_LANG 80349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<void>::other; 81e8d8bef9SDimitry Andric #else 82349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<void>; 83e8d8bef9SDimitry Andric #endif 84e8d8bef9SDimitry Andric }; 85e8d8bef9SDimitry Andric 86e8d8bef9SDimitry Andric // __const_void_pointer 87e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_const_void_pointer, const_void_pointer); 88cb14a3feSDimitry Andric template <class _Ptr, class _Alloc, bool = __has_const_void_pointer<_Alloc>::value> 89e8d8bef9SDimitry Andric struct __const_void_pointer { 90349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::const_void_pointer; 91e8d8bef9SDimitry Andric }; 92e8d8bef9SDimitry Andric template <class _Ptr, class _Alloc> 93e8d8bef9SDimitry Andric struct __const_void_pointer<_Ptr, _Alloc, false> { 94e8d8bef9SDimitry Andric #ifdef _LIBCPP_CXX03_LANG 95349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const void>::other; 96e8d8bef9SDimitry Andric #else 97349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::template rebind<const void>; 98e8d8bef9SDimitry Andric #endif 99e8d8bef9SDimitry Andric }; 100e8d8bef9SDimitry Andric 101e8d8bef9SDimitry Andric // __size_type 102e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_size_type, size_type); 103e8d8bef9SDimitry Andric template <class _Alloc, class _DiffType, bool = __has_size_type<_Alloc>::value> 104e8d8bef9SDimitry Andric struct __size_type : make_unsigned<_DiffType> {}; 105e8d8bef9SDimitry Andric template <class _Alloc, class _DiffType> 106e8d8bef9SDimitry Andric struct __size_type<_Alloc, _DiffType, true> { 107349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::size_type; 108e8d8bef9SDimitry Andric }; 109e8d8bef9SDimitry Andric 110e8d8bef9SDimitry Andric // __alloc_traits_difference_type 111e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_alloc_traits_difference_type, difference_type); 112e8d8bef9SDimitry Andric template <class _Alloc, class _Ptr, bool = __has_alloc_traits_difference_type<_Alloc>::value> 113e8d8bef9SDimitry Andric struct __alloc_traits_difference_type { 114349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename pointer_traits<_Ptr>::difference_type; 115e8d8bef9SDimitry Andric }; 116e8d8bef9SDimitry Andric template <class _Alloc, class _Ptr> 117e8d8bef9SDimitry Andric struct __alloc_traits_difference_type<_Alloc, _Ptr, true> { 118349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::difference_type; 119e8d8bef9SDimitry Andric }; 120e8d8bef9SDimitry Andric 121e8d8bef9SDimitry Andric // __propagate_on_container_copy_assignment 122e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_copy_assignment, propagate_on_container_copy_assignment); 123e8d8bef9SDimitry Andric template <class _Alloc, bool = __has_propagate_on_container_copy_assignment<_Alloc>::value> 124e8d8bef9SDimitry Andric struct __propagate_on_container_copy_assignment : false_type {}; 125e8d8bef9SDimitry Andric template <class _Alloc> 126e8d8bef9SDimitry Andric struct __propagate_on_container_copy_assignment<_Alloc, true> { 127349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_copy_assignment; 128e8d8bef9SDimitry Andric }; 129e8d8bef9SDimitry Andric 130e8d8bef9SDimitry Andric // __propagate_on_container_move_assignment 131e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_move_assignment, propagate_on_container_move_assignment); 132e8d8bef9SDimitry Andric template <class _Alloc, bool = __has_propagate_on_container_move_assignment<_Alloc>::value> 133e8d8bef9SDimitry Andric struct __propagate_on_container_move_assignment : false_type {}; 134e8d8bef9SDimitry Andric template <class _Alloc> 135e8d8bef9SDimitry Andric struct __propagate_on_container_move_assignment<_Alloc, true> { 136349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_move_assignment; 137e8d8bef9SDimitry Andric }; 138e8d8bef9SDimitry Andric 139e8d8bef9SDimitry Andric // __propagate_on_container_swap 140e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_propagate_on_container_swap, propagate_on_container_swap); 141e8d8bef9SDimitry Andric template <class _Alloc, bool = __has_propagate_on_container_swap<_Alloc>::value> 142e8d8bef9SDimitry Andric struct __propagate_on_container_swap : false_type {}; 143e8d8bef9SDimitry Andric template <class _Alloc> 144e8d8bef9SDimitry Andric struct __propagate_on_container_swap<_Alloc, true> { 145349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::propagate_on_container_swap; 146e8d8bef9SDimitry Andric }; 147e8d8bef9SDimitry Andric 148e8d8bef9SDimitry Andric // __is_always_equal 149e8d8bef9SDimitry Andric _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX(__has_is_always_equal, is_always_equal); 150e8d8bef9SDimitry Andric template <class _Alloc, bool = __has_is_always_equal<_Alloc>::value> 151e8d8bef9SDimitry Andric struct __is_always_equal : is_empty<_Alloc> {}; 152e8d8bef9SDimitry Andric template <class _Alloc> 153e8d8bef9SDimitry Andric struct __is_always_equal<_Alloc, true> { 154349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc::is_always_equal; 155e8d8bef9SDimitry Andric }; 156e8d8bef9SDimitry Andric 157e8d8bef9SDimitry Andric // __allocator_traits_rebind 158e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 159e8d8bef9SDimitry Andric template <class _Tp, class _Up, class = void> 160e8d8bef9SDimitry Andric struct __has_rebind_other : false_type {}; 161e8d8bef9SDimitry Andric template <class _Tp, class _Up> 162bdd1243dSDimitry Andric struct __has_rebind_other<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>::other> > : true_type {}; 163e8d8bef9SDimitry Andric 164e8d8bef9SDimitry Andric template <class _Tp, class _Up, bool = __has_rebind_other<_Tp, _Up>::value> 165e8d8bef9SDimitry Andric struct __allocator_traits_rebind { 166bdd1243dSDimitry Andric static_assert(__has_rebind_other<_Tp, _Up>::value, "This allocator has to implement rebind"); 167349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other; 168e8d8bef9SDimitry Andric }; 169e8d8bef9SDimitry Andric template <template <class, class...> class _Alloc, class _Tp, class... _Args, class _Up> 170e8d8bef9SDimitry Andric struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, true> { 171349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = typename _Alloc<_Tp, _Args...>::template rebind<_Up>::other; 172e8d8bef9SDimitry Andric }; 173e8d8bef9SDimitry Andric template <template <class, class...> class _Alloc, class _Tp, class... _Args, class _Up> 174e8d8bef9SDimitry Andric struct __allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, false> { 175349cc55cSDimitry Andric using type _LIBCPP_NODEBUG = _Alloc<_Up, _Args...>; 176e8d8bef9SDimitry Andric }; 177e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 178e8d8bef9SDimitry Andric 179e8d8bef9SDimitry Andric template <class _Alloc, class _Tp> 180e8d8bef9SDimitry Andric using __allocator_traits_rebind_t = typename __allocator_traits_rebind<_Alloc, _Tp>::type; 181e8d8bef9SDimitry Andric 182e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 183e8d8bef9SDimitry Andric 184e8d8bef9SDimitry Andric // __has_allocate_hint 185e8d8bef9SDimitry Andric template <class _Alloc, class _SizeType, class _ConstVoidPtr, class = void> 186e8d8bef9SDimitry Andric struct __has_allocate_hint : false_type {}; 187e8d8bef9SDimitry Andric 188e8d8bef9SDimitry Andric template <class _Alloc, class _SizeType, class _ConstVoidPtr> 189cb14a3feSDimitry Andric struct __has_allocate_hint< 190cb14a3feSDimitry Andric _Alloc, 191cb14a3feSDimitry Andric _SizeType, 192cb14a3feSDimitry Andric _ConstVoidPtr, 193cb14a3feSDimitry Andric decltype((void)std::declval<_Alloc>().allocate(std::declval<_SizeType>(), std::declval<_ConstVoidPtr>()))> 194cb14a3feSDimitry Andric : true_type {}; 195e8d8bef9SDimitry Andric 196e8d8bef9SDimitry Andric // __has_construct 197e8d8bef9SDimitry Andric template <class, class _Alloc, class... _Args> 198e8d8bef9SDimitry Andric struct __has_construct_impl : false_type {}; 199e8d8bef9SDimitry Andric 200e8d8bef9SDimitry Andric template <class _Alloc, class... _Args> 201cb14a3feSDimitry Andric struct __has_construct_impl<decltype((void)std::declval<_Alloc>().construct(std::declval<_Args>()...)), 202cb14a3feSDimitry Andric _Alloc, 203cb14a3feSDimitry Andric _Args...> : true_type {}; 204e8d8bef9SDimitry Andric 205e8d8bef9SDimitry Andric template <class _Alloc, class... _Args> 206e8d8bef9SDimitry Andric struct __has_construct : __has_construct_impl<void, _Alloc, _Args...> {}; 207e8d8bef9SDimitry Andric 208e8d8bef9SDimitry Andric // __has_destroy 209e8d8bef9SDimitry Andric template <class _Alloc, class _Pointer, class = void> 210e8d8bef9SDimitry Andric struct __has_destroy : false_type {}; 211e8d8bef9SDimitry Andric 212e8d8bef9SDimitry Andric template <class _Alloc, class _Pointer> 213cb14a3feSDimitry Andric struct __has_destroy<_Alloc, _Pointer, decltype((void)std::declval<_Alloc>().destroy(std::declval<_Pointer>()))> 214cb14a3feSDimitry Andric : true_type {}; 215e8d8bef9SDimitry Andric 216e8d8bef9SDimitry Andric // __has_max_size 217e8d8bef9SDimitry Andric template <class _Alloc, class = void> 218e8d8bef9SDimitry Andric struct __has_max_size : false_type {}; 219e8d8bef9SDimitry Andric 220e8d8bef9SDimitry Andric template <class _Alloc> 221cb14a3feSDimitry Andric struct __has_max_size<_Alloc, decltype((void)std::declval<_Alloc&>().max_size())> : true_type {}; 222e8d8bef9SDimitry Andric 223e8d8bef9SDimitry Andric // __has_select_on_container_copy_construction 224e8d8bef9SDimitry Andric template <class _Alloc, class = void> 225e8d8bef9SDimitry Andric struct __has_select_on_container_copy_construction : false_type {}; 226e8d8bef9SDimitry Andric 227e8d8bef9SDimitry Andric template <class _Alloc> 228cb14a3feSDimitry Andric struct __has_select_on_container_copy_construction< 229cb14a3feSDimitry Andric _Alloc, 230cb14a3feSDimitry Andric decltype((void)std::declval<_Alloc>().select_on_container_copy_construction())> : true_type {}; 231e8d8bef9SDimitry Andric 232e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 233e8d8bef9SDimitry Andric 234*0fca6ea1SDimitry Andric #if _LIBCPP_STD_VER >= 23 235*0fca6ea1SDimitry Andric 236*0fca6ea1SDimitry Andric template <class _Pointer, class _SizeType = size_t> 237*0fca6ea1SDimitry Andric struct allocation_result { 238*0fca6ea1SDimitry Andric _Pointer ptr; 239*0fca6ea1SDimitry Andric _SizeType count; 240*0fca6ea1SDimitry Andric }; 241*0fca6ea1SDimitry Andric _LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result); 242*0fca6ea1SDimitry Andric 243*0fca6ea1SDimitry Andric #endif // _LIBCPP_STD_VER 244*0fca6ea1SDimitry Andric 245e8d8bef9SDimitry Andric template <class _Alloc> 246cb14a3feSDimitry Andric struct _LIBCPP_TEMPLATE_VIS allocator_traits { 247e8d8bef9SDimitry Andric using allocator_type = _Alloc; 248e8d8bef9SDimitry Andric using value_type = typename allocator_type::value_type; 249e8d8bef9SDimitry Andric using pointer = typename __pointer<value_type, allocator_type>::type; 250e8d8bef9SDimitry Andric using const_pointer = typename __const_pointer<value_type, pointer, allocator_type>::type; 251e8d8bef9SDimitry Andric using void_pointer = typename __void_pointer<pointer, allocator_type>::type; 252e8d8bef9SDimitry Andric using const_void_pointer = typename __const_void_pointer<pointer, allocator_type>::type; 253e8d8bef9SDimitry Andric using difference_type = typename __alloc_traits_difference_type<allocator_type, pointer>::type; 254e8d8bef9SDimitry Andric using size_type = typename __size_type<allocator_type, difference_type>::type; 255cb14a3feSDimitry Andric using propagate_on_container_copy_assignment = 256cb14a3feSDimitry Andric typename __propagate_on_container_copy_assignment<allocator_type>::type; 257cb14a3feSDimitry Andric using propagate_on_container_move_assignment = 258cb14a3feSDimitry Andric typename __propagate_on_container_move_assignment<allocator_type>::type; 259e8d8bef9SDimitry Andric using propagate_on_container_swap = typename __propagate_on_container_swap<allocator_type>::type; 260e8d8bef9SDimitry Andric using is_always_equal = typename __is_always_equal<allocator_type>::type; 261e8d8bef9SDimitry Andric 262e8d8bef9SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 263e8d8bef9SDimitry Andric template <class _Tp> 264e8d8bef9SDimitry Andric using rebind_alloc = __allocator_traits_rebind_t<allocator_type, _Tp>; 265e8d8bef9SDimitry Andric template <class _Tp> 266e8d8bef9SDimitry Andric using rebind_traits = allocator_traits<rebind_alloc<_Tp> >; 267e8d8bef9SDimitry Andric #else // _LIBCPP_CXX03_LANG 268e8d8bef9SDimitry Andric template <class _Tp> 269e8d8bef9SDimitry Andric struct rebind_alloc { 270e8d8bef9SDimitry Andric using other = __allocator_traits_rebind_t<allocator_type, _Tp>; 271e8d8bef9SDimitry Andric }; 272e8d8bef9SDimitry Andric template <class _Tp> 273e8d8bef9SDimitry Andric struct rebind_traits { 274e8d8bef9SDimitry Andric using other = allocator_traits<typename rebind_alloc<_Tp>::other>; 275e8d8bef9SDimitry Andric }; 276e8d8bef9SDimitry Andric #endif // _LIBCPP_CXX03_LANG 277e8d8bef9SDimitry Andric 278*0fca6ea1SDimitry Andric _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer 279cb14a3feSDimitry Andric allocate(allocator_type& __a, size_type __n) { 280e8d8bef9SDimitry Andric return __a.allocate(__n); 281e8d8bef9SDimitry Andric } 282e8d8bef9SDimitry Andric 283*0fca6ea1SDimitry Andric template <class _Ap = _Alloc, __enable_if_t<__has_allocate_hint<_Ap, size_type, const_void_pointer>::value, int> = 0> 284*0fca6ea1SDimitry Andric _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer 285cb14a3feSDimitry Andric allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) { 286e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 287e8d8bef9SDimitry Andric return __a.allocate(__n, __hint); 288e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 289e8d8bef9SDimitry Andric } 290cb14a3feSDimitry Andric template <class _Ap = _Alloc, 291cb14a3feSDimitry Andric class = void, 292*0fca6ea1SDimitry Andric __enable_if_t<!__has_allocate_hint<_Ap, size_type, const_void_pointer>::value, int> = 0> 293*0fca6ea1SDimitry Andric _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer 294cb14a3feSDimitry Andric allocate(allocator_type& __a, size_type __n, const_void_pointer) { 295e8d8bef9SDimitry Andric return __a.allocate(__n); 296e8d8bef9SDimitry Andric } 297e8d8bef9SDimitry Andric 298*0fca6ea1SDimitry Andric #if _LIBCPP_STD_VER >= 23 299*0fca6ea1SDimitry Andric template <class _Ap = _Alloc> 300*0fca6ea1SDimitry Andric [[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr allocation_result<pointer, size_type> 301*0fca6ea1SDimitry Andric allocate_at_least(_Ap& __alloc, size_type __n) { 302*0fca6ea1SDimitry Andric if constexpr (requires { __alloc.allocate_at_least(__n); }) { 303*0fca6ea1SDimitry Andric return __alloc.allocate_at_least(__n); 304*0fca6ea1SDimitry Andric } else { 305*0fca6ea1SDimitry Andric return {__alloc.allocate(__n), __n}; 306*0fca6ea1SDimitry Andric } 307*0fca6ea1SDimitry Andric } 308*0fca6ea1SDimitry Andric #endif 309*0fca6ea1SDimitry Andric 310cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void 311cb14a3feSDimitry Andric deallocate(allocator_type& __a, pointer __p, size_type __n) _NOEXCEPT { 312e8d8bef9SDimitry Andric __a.deallocate(__p, __n); 313e8d8bef9SDimitry Andric } 314e8d8bef9SDimitry Andric 315*0fca6ea1SDimitry Andric template <class _Tp, class... _Args, __enable_if_t<__has_construct<allocator_type, _Tp*, _Args...>::value, int> = 0> 316cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void 317cb14a3feSDimitry Andric construct(allocator_type& __a, _Tp* __p, _Args&&... __args) { 318e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 3195f757f3fSDimitry Andric __a.construct(__p, std::forward<_Args>(__args)...); 320e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 321e8d8bef9SDimitry Andric } 322cb14a3feSDimitry Andric template <class _Tp, 323cb14a3feSDimitry Andric class... _Args, 324cb14a3feSDimitry Andric class = void, 325*0fca6ea1SDimitry Andric __enable_if_t<!__has_construct<allocator_type, _Tp*, _Args...>::value, int> = 0> 326cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void 327cb14a3feSDimitry Andric construct(allocator_type&, _Tp* __p, _Args&&... __args) { 3285f757f3fSDimitry Andric std::__construct_at(__p, std::forward<_Args>(__args)...); 329e8d8bef9SDimitry Andric } 330e8d8bef9SDimitry Andric 331*0fca6ea1SDimitry Andric template <class _Tp, __enable_if_t<__has_destroy<allocator_type, _Tp*>::value, int> = 0> 332cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type& __a, _Tp* __p) { 333e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 334e8d8bef9SDimitry Andric __a.destroy(__p); 335e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 336e8d8bef9SDimitry Andric } 337*0fca6ea1SDimitry Andric template <class _Tp, class = void, __enable_if_t<!__has_destroy<allocator_type, _Tp*>::value, int> = 0> 338cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static void destroy(allocator_type&, _Tp* __p) { 3395f757f3fSDimitry Andric std::__destroy_at(__p); 340e8d8bef9SDimitry Andric } 341e8d8bef9SDimitry Andric 342*0fca6ea1SDimitry Andric template <class _Ap = _Alloc, __enable_if_t<__has_max_size<const _Ap>::value, int> = 0> 343cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type& __a) _NOEXCEPT { 344e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_PUSH 345e8d8bef9SDimitry Andric return __a.max_size(); 346e8d8bef9SDimitry Andric _LIBCPP_SUPPRESS_DEPRECATED_POP 347e8d8bef9SDimitry Andric } 348*0fca6ea1SDimitry Andric template <class _Ap = _Alloc, class = void, __enable_if_t<!__has_max_size<const _Ap>::value, int> = 0> 349cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static size_type max_size(const allocator_type&) _NOEXCEPT { 350e8d8bef9SDimitry Andric return numeric_limits<size_type>::max() / sizeof(value_type); 351e8d8bef9SDimitry Andric } 352e8d8bef9SDimitry Andric 353*0fca6ea1SDimitry Andric template <class _Ap = _Alloc, __enable_if_t<__has_select_on_container_copy_construction<const _Ap>::value, int> = 0> 354cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type 355cb14a3feSDimitry Andric select_on_container_copy_construction(const allocator_type& __a) { 356e8d8bef9SDimitry Andric return __a.select_on_container_copy_construction(); 357e8d8bef9SDimitry Andric } 358cb14a3feSDimitry Andric template <class _Ap = _Alloc, 359cb14a3feSDimitry Andric class = void, 360*0fca6ea1SDimitry Andric __enable_if_t<!__has_select_on_container_copy_construction<const _Ap>::value, int> = 0> 361cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static allocator_type 362cb14a3feSDimitry Andric select_on_container_copy_construction(const allocator_type& __a) { 363e8d8bef9SDimitry Andric return __a; 364e8d8bef9SDimitry Andric } 365e8d8bef9SDimitry Andric }; 366e8d8bef9SDimitry Andric 367e8d8bef9SDimitry Andric #ifndef _LIBCPP_CXX03_LANG 368bdd1243dSDimitry Andric template <class _Traits, class _Tp> 369bdd1243dSDimitry Andric using __rebind_alloc _LIBCPP_NODEBUG = typename _Traits::template rebind_alloc<_Tp>; 370e8d8bef9SDimitry Andric #else 371bdd1243dSDimitry Andric template <class _Traits, class _Tp> 372bdd1243dSDimitry Andric using __rebind_alloc = typename _Traits::template rebind_alloc<_Tp>::other; 373e8d8bef9SDimitry Andric #endif 374e8d8bef9SDimitry Andric 375*0fca6ea1SDimitry Andric template <class _Alloc> 376*0fca6ea1SDimitry Andric struct __check_valid_allocator : true_type { 377*0fca6ea1SDimitry Andric using _Traits = std::allocator_traits<_Alloc>; 378*0fca6ea1SDimitry Andric static_assert(is_same<_Alloc, __rebind_alloc<_Traits, typename _Traits::value_type> >::value, 379*0fca6ea1SDimitry Andric "[allocator.requirements] states that rebinding an allocator to the same type should result in the " 380*0fca6ea1SDimitry Andric "original allocator"); 381*0fca6ea1SDimitry Andric }; 382*0fca6ea1SDimitry Andric 383e8d8bef9SDimitry Andric // __is_default_allocator 384e8d8bef9SDimitry Andric template <class _Tp> 385e8d8bef9SDimitry Andric struct __is_default_allocator : false_type {}; 386e8d8bef9SDimitry Andric 387cb14a3feSDimitry Andric template <class> 388cb14a3feSDimitry Andric class allocator; 389fe6060f1SDimitry Andric 390e8d8bef9SDimitry Andric template <class _Tp> 391fe6060f1SDimitry Andric struct __is_default_allocator<allocator<_Tp> > : true_type {}; 392e8d8bef9SDimitry Andric 393e8d8bef9SDimitry Andric // __is_cpp17_move_insertable 394e8d8bef9SDimitry Andric template <class _Alloc, class = void> 395cb14a3feSDimitry Andric struct __is_cpp17_move_insertable : is_move_constructible<typename _Alloc::value_type> {}; 396e8d8bef9SDimitry Andric 397e8d8bef9SDimitry Andric template <class _Alloc> 398cb14a3feSDimitry Andric struct __is_cpp17_move_insertable< 399cb14a3feSDimitry Andric _Alloc, 400cb14a3feSDimitry Andric __enable_if_t< !__is_default_allocator<_Alloc>::value && 401cb14a3feSDimitry Andric __has_construct<_Alloc, typename _Alloc::value_type*, typename _Alloc::value_type&&>::value > > 402cb14a3feSDimitry Andric : true_type {}; 403e8d8bef9SDimitry Andric 404e8d8bef9SDimitry Andric // __is_cpp17_copy_insertable 405e8d8bef9SDimitry Andric template <class _Alloc, class = void> 406e8d8bef9SDimitry Andric struct __is_cpp17_copy_insertable 407e8d8bef9SDimitry Andric : integral_constant<bool, 408e8d8bef9SDimitry Andric is_copy_constructible<typename _Alloc::value_type>::value && 409cb14a3feSDimitry Andric __is_cpp17_move_insertable<_Alloc>::value > {}; 410e8d8bef9SDimitry Andric 411e8d8bef9SDimitry Andric template <class _Alloc> 412cb14a3feSDimitry Andric struct __is_cpp17_copy_insertable< 413cb14a3feSDimitry Andric _Alloc, 414cb14a3feSDimitry Andric __enable_if_t< !__is_default_allocator<_Alloc>::value && 415cb14a3feSDimitry Andric __has_construct<_Alloc, typename _Alloc::value_type*, const typename _Alloc::value_type&>::value > > 416cb14a3feSDimitry Andric : __is_cpp17_move_insertable<_Alloc> {}; 417e8d8bef9SDimitry Andric 418e8d8bef9SDimitry Andric #undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX 419e8d8bef9SDimitry Andric 420e8d8bef9SDimitry Andric _LIBCPP_END_NAMESPACE_STD 421e8d8bef9SDimitry Andric 422e8d8bef9SDimitry Andric _LIBCPP_POP_MACROS 423e8d8bef9SDimitry Andric 424e8d8bef9SDimitry Andric #endif // _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H 425