File indexing completed on 2026-05-03 08:13:57
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
0010 #define _LIBCPP___MEMORY_RESOURCE_POLYMORPHIC_ALLOCATOR_H
0011
0012 #include <__assert>
0013 #include <__config>
0014 #include <__cstddef/byte.h>
0015 #include <__cstddef/max_align_t.h>
0016 #include <__fwd/pair.h>
0017 #include <__memory_resource/memory_resource.h>
0018 #include <__new/exceptions.h>
0019 #include <__new/placement_new_delete.h>
0020 #include <__utility/exception_guard.h>
0021 #include <limits>
0022 #include <tuple>
0023
0024 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0025 # pragma GCC system_header
0026 #endif
0027
0028 _LIBCPP_PUSH_MACROS
0029 #include <__undef_macros>
0030
0031 #if _LIBCPP_STD_VER >= 17
0032
0033 _LIBCPP_BEGIN_NAMESPACE_STD
0034
0035 namespace pmr {
0036
0037
0038
0039 template <class _ValueType
0040 # if _LIBCPP_STD_VER >= 20
0041 = byte
0042 # endif
0043 >
0044 class _LIBCPP_AVAILABILITY_PMR _LIBCPP_TEMPLATE_VIS polymorphic_allocator {
0045
0046 public:
0047 using value_type = _ValueType;
0048
0049
0050
0051 _LIBCPP_HIDE_FROM_ABI polymorphic_allocator() noexcept : __res_(std::pmr::get_default_resource()) {}
0052
0053 _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(memory_resource* __r) noexcept : __res_(__r) {}
0054
0055 _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator&) = default;
0056
0057 template <class _Tp>
0058 _LIBCPP_HIDE_FROM_ABI polymorphic_allocator(const polymorphic_allocator<_Tp>& __other) noexcept
0059 : __res_(__other.resource()) {}
0060
0061 polymorphic_allocator& operator=(const polymorphic_allocator&) = delete;
0062
0063
0064
0065 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _ValueType* allocate(size_t __n) {
0066 if (__n > __max_size()) {
0067 __throw_bad_array_new_length();
0068 }
0069 return static_cast<_ValueType*>(__res_->allocate(__n * sizeof(_ValueType), alignof(_ValueType)));
0070 }
0071
0072 _LIBCPP_HIDE_FROM_ABI void deallocate(_ValueType* __p, size_t __n) {
0073 _LIBCPP_ASSERT_VALID_DEALLOCATION(
0074 __n <= __max_size(),
0075 "deallocate() called for a size which exceeds max_size(), leading to a memory leak "
0076 "(the argument will overflow and result in too few objects being deleted)");
0077 __res_->deallocate(__p, __n * sizeof(_ValueType), alignof(_ValueType));
0078 }
0079
0080 # if _LIBCPP_STD_VER >= 20
0081
0082 [[nodiscard]] [[using __gnu__: __alloc_size__(2), __alloc_align__(3)]] _LIBCPP_HIDE_FROM_ABI void*
0083 allocate_bytes(size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
0084 return __res_->allocate(__nbytes, __alignment);
0085 }
0086
0087 _LIBCPP_HIDE_FROM_ABI void deallocate_bytes(void* __ptr, size_t __nbytes, size_t __alignment = alignof(max_align_t)) {
0088 __res_->deallocate(__ptr, __nbytes, __alignment);
0089 }
0090
0091 template <class _Type>
0092 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* allocate_object(size_t __n = 1) {
0093 if (numeric_limits<size_t>::max() / sizeof(_Type) < __n)
0094 std::__throw_bad_array_new_length();
0095 return static_cast<_Type*>(allocate_bytes(__n * sizeof(_Type), alignof(_Type)));
0096 }
0097
0098 template <class _Type>
0099 _LIBCPP_HIDE_FROM_ABI void deallocate_object(_Type* __ptr, size_t __n = 1) {
0100 deallocate_bytes(__ptr, __n * sizeof(_Type), alignof(_Type));
0101 }
0102
0103 template <class _Type, class... _CtorArgs>
0104 [[nodiscard]] _LIBCPP_HIDE_FROM_ABI _Type* new_object(_CtorArgs&&... __ctor_args) {
0105 _Type* __ptr = allocate_object<_Type>();
0106 auto __guard = std::__make_exception_guard([&] { deallocate_object(__ptr); });
0107 construct(__ptr, std::forward<_CtorArgs>(__ctor_args)...);
0108 __guard.__complete();
0109 return __ptr;
0110 }
0111
0112 template <class _Type>
0113 _LIBCPP_HIDE_FROM_ABI void delete_object(_Type* __ptr) {
0114 destroy(__ptr);
0115 deallocate_object(__ptr);
0116 }
0117
0118 # endif
0119
0120 template <class _Tp, class... _Ts>
0121 _LIBCPP_HIDE_FROM_ABI void construct(_Tp* __p, _Ts&&... __args) {
0122 std::__user_alloc_construct_impl(
0123 typename __uses_alloc_ctor<_Tp, polymorphic_allocator&, _Ts...>::type(),
0124 __p,
0125 *this,
0126 std::forward<_Ts>(__args)...);
0127 }
0128
0129 template <class _T1, class _T2, class... _Args1, class... _Args2>
0130 _LIBCPP_HIDE_FROM_ABI void
0131 construct(pair<_T1, _T2>* __p, piecewise_construct_t, tuple<_Args1...> __x, tuple<_Args2...> __y) {
0132 ::new ((void*)__p) pair<_T1, _T2>(
0133 piecewise_construct,
0134 __transform_tuple(typename __uses_alloc_ctor< _T1, polymorphic_allocator&, _Args1... >::type(),
0135 std::move(__x),
0136 typename __make_tuple_indices<sizeof...(_Args1)>::type{}),
0137 __transform_tuple(typename __uses_alloc_ctor< _T2, polymorphic_allocator&, _Args2... >::type(),
0138 std::move(__y),
0139 typename __make_tuple_indices<sizeof...(_Args2)>::type{}));
0140 }
0141
0142 template <class _T1, class _T2>
0143 _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p) {
0144 construct(__p, piecewise_construct, tuple<>(), tuple<>());
0145 }
0146
0147 template <class _T1, class _T2, class _Up, class _Vp>
0148 _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) {
0149 construct(__p,
0150 piecewise_construct,
0151 std::forward_as_tuple(std::forward<_Up>(__u)),
0152 std::forward_as_tuple(std::forward<_Vp>(__v)));
0153 }
0154
0155 template <class _T1, class _T2, class _U1, class _U2>
0156 _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, const pair<_U1, _U2>& __pr) {
0157 construct(__p, piecewise_construct, std::forward_as_tuple(__pr.first), std::forward_as_tuple(__pr.second));
0158 }
0159
0160 template <class _T1, class _T2, class _U1, class _U2>
0161 _LIBCPP_HIDE_FROM_ABI void construct(pair<_T1, _T2>* __p, pair<_U1, _U2>&& __pr) {
0162 construct(__p,
0163 piecewise_construct,
0164 std::forward_as_tuple(std::forward<_U1>(__pr.first)),
0165 std::forward_as_tuple(std::forward<_U2>(__pr.second)));
0166 }
0167
0168 template <class _Tp>
0169 _LIBCPP_HIDE_FROM_ABI void destroy(_Tp* __p) {
0170 __p->~_Tp();
0171 }
0172
0173 _LIBCPP_HIDE_FROM_ABI polymorphic_allocator select_on_container_copy_construction() const noexcept {
0174 return polymorphic_allocator();
0175 }
0176
0177 _LIBCPP_HIDE_FROM_ABI memory_resource* resource() const noexcept { return __res_; }
0178
0179 _LIBCPP_HIDE_FROM_ABI friend bool
0180 operator==(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {
0181 return *__lhs.resource() == *__rhs.resource();
0182 }
0183
0184 # if _LIBCPP_STD_VER <= 17
0185
0186 _LIBCPP_HIDE_FROM_ABI friend bool
0187 operator!=(const polymorphic_allocator& __lhs, const polymorphic_allocator& __rhs) noexcept {
0188 return *__lhs.resource() != *__rhs.resource();
0189 }
0190 # endif
0191
0192 private:
0193 template <class... _Args, size_t... _Is>
0194 _LIBCPP_HIDE_FROM_ABI tuple<_Args&&...>
0195 __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0196 return std::forward_as_tuple(std::get<_Is>(std::move(__t))...);
0197 }
0198
0199 template <class... _Args, size_t... _Is>
0200 _LIBCPP_HIDE_FROM_ABI tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>
0201 __transform_tuple(integral_constant<int, 1>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0202 using _Tup = tuple<allocator_arg_t const&, polymorphic_allocator&, _Args&&...>;
0203 return _Tup(allocator_arg, *this, std::get<_Is>(std::move(__t))...);
0204 }
0205
0206 template <class... _Args, size_t... _Is>
0207 _LIBCPP_HIDE_FROM_ABI tuple<_Args&&..., polymorphic_allocator&>
0208 __transform_tuple(integral_constant<int, 2>, tuple<_Args...>&& __t, __tuple_indices<_Is...>) {
0209 using _Tup = tuple<_Args&&..., polymorphic_allocator&>;
0210 return _Tup(std::get<_Is>(std::move(__t))..., *this);
0211 }
0212
0213 _LIBCPP_HIDE_FROM_ABI size_t __max_size() const noexcept {
0214 return numeric_limits<size_t>::max() / sizeof(value_type);
0215 }
0216
0217 memory_resource* __res_;
0218 };
0219
0220
0221
0222 template <class _Tp, class _Up>
0223 inline _LIBCPP_HIDE_FROM_ABI bool
0224 operator==(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
0225 return *__lhs.resource() == *__rhs.resource();
0226 }
0227
0228 # if _LIBCPP_STD_VER <= 17
0229
0230 template <class _Tp, class _Up>
0231 inline _LIBCPP_HIDE_FROM_ABI bool
0232 operator!=(const polymorphic_allocator<_Tp>& __lhs, const polymorphic_allocator<_Up>& __rhs) noexcept {
0233 return !(__lhs == __rhs);
0234 }
0235
0236 # endif
0237
0238 }
0239
0240 _LIBCPP_END_NAMESPACE_STD
0241
0242 #endif
0243
0244 _LIBCPP_POP_MACROS
0245
0246 #endif