30 #ifndef _GLIBCXX_MEMORY_RESOURCE_H
31 #define _GLIBCXX_MEMORY_RESOURCE_H 1
33 #pragma GCC system_header
35 #if __cplusplus >= 201703L
40 #include <bits/uses_allocator.h>
45 #if ! __cpp_lib_make_obj_using_allocator
50 namespace std _GLIBCXX_VISIBILITY(default)
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
63 static constexpr
size_t _S_max_align =
alignof(max_align_t);
74 allocate(
size_t __bytes,
size_t __alignment = _S_max_align)
75 __attribute__((__returns_nonnull__,__alloc_size__(2),__alloc_align__(3)))
76 { return ::operator
new(__bytes, do_allocate(__bytes, __alignment)); }
79 deallocate(
void* __p,
size_t __bytes,
size_t __alignment = _S_max_align)
80 __attribute__((__nonnull__))
81 {
return do_deallocate(__p, __bytes, __alignment); }
86 {
return do_is_equal(__other); }
90 do_allocate(
size_t __bytes,
size_t __alignment) = 0;
93 do_deallocate(
void* __p,
size_t __bytes,
size_t __alignment) = 0;
102 {
return &__a == &__b || __a.is_equal(__b); }
104 #if __cpp_impl_three_way_comparison < 201907L
107 operator!=(
const memory_resource& __a,
const memory_resource& __b) noexcept
108 {
return !(__a == __b); }
119 template<
typename _Tp>
120 class polymorphic_allocator
124 template<
typename _Up>
125 struct __not_pair {
using type = void; };
127 template<
typename _Up1,
typename _Up2>
128 struct __not_pair<pair<_Up1, _Up2>> { };
131 using value_type = _Tp;
133 polymorphic_allocator() noexcept
136 __attribute__((__returns_nonnull__));
137 _M_resource = get_default_resource();
140 polymorphic_allocator(memory_resource* __r) noexcept
141 __attribute__((__nonnull__))
143 { _GLIBCXX_DEBUG_ASSERT(__r); }
145 polymorphic_allocator(
const polymorphic_allocator& __other) =
default;
147 template<
typename _Up>
148 polymorphic_allocator(
const polymorphic_allocator<_Up>& __x) noexcept
149 : _M_resource(__x.resource())
152 polymorphic_allocator&
153 operator=(
const polymorphic_allocator&) =
delete;
158 __attribute__((__returns_nonnull__))
161 std::__throw_bad_array_new_length();
162 return static_cast<_Tp*
>(_M_resource->allocate(__n *
sizeof(_Tp),
167 deallocate(_Tp* __p,
size_t __n) noexcept
168 __attribute__((__nonnull__))
169 { _M_resource->deallocate(__p, __n *
sizeof(_Tp),
alignof(_Tp)); }
171 #if __cplusplus > 201703L
173 allocate_bytes(
size_t __nbytes,
174 size_t __alignment =
alignof(max_align_t))
175 {
return _M_resource->allocate(__nbytes, __alignment); }
178 deallocate_bytes(
void* __p,
size_t __nbytes,
179 size_t __alignment =
alignof(max_align_t))
180 { _M_resource->deallocate(__p, __nbytes, __alignment); }
182 template<
typename _Up>
184 allocate_object(
size_t __n = 1)
187 std::__throw_bad_array_new_length();
188 return static_cast<_Up*
>(allocate_bytes(__n *
sizeof(_Up),
192 template<
typename _Up>
194 deallocate_object(_Up* __p,
size_t __n = 1)
195 { deallocate_bytes(__p, __n *
sizeof(_Up),
alignof(_Up)); }
197 template<
typename _Up,
typename... _CtorArgs>
199 new_object(_CtorArgs&&... __ctor_args)
201 _Up* __p = allocate_object<_Up>();
204 construct(__p, std::forward<_CtorArgs>(__ctor_args)...);
208 deallocate_object(__p);
209 __throw_exception_again;
214 template<
typename _Up>
216 delete_object(_Up* __p)
219 deallocate_object(__p);
223 #if ! __cpp_lib_make_obj_using_allocator
224 template<
typename _Tp1,
typename... _Args>
225 __attribute__((__nonnull__))
226 typename __not_pair<_Tp1>::type
227 construct(_Tp1* __p, _Args&&... __args)
232 = std::__uses_alloc_t<_Tp1, polymorphic_allocator, _Args...>;
233 if constexpr (is_base_of_v<__uses_alloc0, __use_tag>)
234 ::new(__p) _Tp1(
std::
forward<_Args>(__args)...);
235 else if constexpr (is_base_of_v<__uses_alloc1_, __use_tag>)
236 ::new(__p) _Tp1(allocator_arg, *this,
239 ::new(__p) _Tp1(std::forward<_Args>(__args)..., *
this);
242 template<
typename _Tp1,
typename _Tp2,
243 typename... _Args1,
typename... _Args2>
244 __attribute__((__nonnull__))
246 construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t,
247 tuple<_Args1...> __x, tuple<_Args2...> __y)
250 __use_alloc<_Tp1, polymorphic_allocator, _Args1...>(*this);
252 __use_alloc<_Tp2, polymorphic_allocator, _Args2...>(*this);
257 _S_construct_p(__x_tag, __x_i, __x),
258 _S_construct_p(__y_tag, __y_i, __y));
261 template<
typename _Tp1,
typename _Tp2>
262 __attribute__((__nonnull__))
264 construct(pair<_Tp1, _Tp2>* __p)
267 template<
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
268 __attribute__((__nonnull__))
270 construct(pair<_Tp1, _Tp2>* __p, _Up&& __x, _Vp&& __y)
277 template <
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
278 __attribute__((__nonnull__))
287 template<
typename _Tp1,
typename _Tp2,
typename _Up,
typename _Vp>
288 __attribute__((__nonnull__))
290 construct(pair<_Tp1, _Tp2>* __p, pair<_Up, _Vp>&& __pr)
296 #else // make_obj_using_allocator
297 template<
typename _Tp1,
typename... _Args>
298 __attribute__((__nonnull__))
300 construct(_Tp1* __p, _Args&&... __args)
302 std::uninitialized_construct_using_allocator(__p, *
this,
303 std::forward<_Args>(__args)...);
307 template<
typename _Up>
308 _GLIBCXX20_DEPRECATED_SUGGEST(
"allocator_traits::destroy")
309 __attribute__((__nonnull__))
314 polymorphic_allocator
315 select_on_container_copy_construction() const noexcept
316 {
return polymorphic_allocator(); }
319 resource() const noexcept
320 __attribute__((__returns_nonnull__))
321 {
return _M_resource; }
327 operator==(
const polymorphic_allocator& __a,
328 const polymorphic_allocator& __b) noexcept
329 {
return *__a.resource() == *__b.resource(); }
331 #if __cpp_impl_three_way_comparison < 201907L
334 operator!=(
const polymorphic_allocator& __a,
335 const polymorphic_allocator& __b) noexcept
336 {
return !(__a == __b); }
340 #if ! __cpp_lib_make_obj_using_allocator
341 using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>;
342 using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
344 template<
typename _Ind,
typename... _Args>
345 static tuple<_Args&&...>
346 _S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t)
349 template<
size_t... _Ind,
typename... _Args>
350 static tuple<allocator_arg_t, polymorphic_allocator, _Args&&...>
351 _S_construct_p(__uses_alloc1_ __ua, index_sequence<_Ind...>,
352 tuple<_Args...>& __t)
355 allocator_arg, *__ua._M_a, std::get<_Ind>(
std::move(__t))...
359 template<
size_t... _Ind,
typename... _Args>
360 static tuple<_Args&&..., polymorphic_allocator>
361 _S_construct_p(__uses_alloc2_ __ua, index_sequence<_Ind...>,
362 tuple<_Args...>& __t)
363 {
return { std::get<_Ind>(
std::move(__t))..., *__ua._M_a }; }
366 memory_resource* _M_resource;
369 template<
typename _Tp1,
typename _Tp2>
372 operator==(
const polymorphic_allocator<_Tp1>& __a,
373 const polymorphic_allocator<_Tp2>& __b) noexcept
374 {
return *__a.resource() == *__b.resource(); }
376 #if __cpp_impl_three_way_comparison < 201907L
377 template<
typename _Tp1,
typename _Tp2>
380 operator!=(
const polymorphic_allocator<_Tp1>& __a,
381 const polymorphic_allocator<_Tp2>& __b) noexcept
382 {
return !(__a == __b); }
387 template<
typename _Alloc>
struct allocator_traits;
390 template<
typename _Tp>
433 template<
typename _Up>
436 template<
typename _Up>
448 {
return __a.allocate(__n); }
461 [[nodiscard]]
static pointer
463 {
return __a.allocate(__n); }
475 { __a.deallocate(__p, __n); }
488 template<
typename _Up,
typename... _Args>
491 { __a.construct(__p, std::forward<_Args>(__args)...); }
500 template<
typename _Up>
501 static _GLIBCXX20_CONSTEXPR
void
510 static _GLIBCXX20_CONSTEXPR size_type
515 _GLIBCXX_END_NAMESPACE_VERSION
519 #endif // _GLIBCXX_MEMORY_RESOURCE_H