Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/memory_resource.h
1 // <memory_resource> -*- C++ -*- 2 3 // Copyright (C) 2018-2025 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file include/bits/memory_resource.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{memory_resource} 28 */ 29 30 #ifndef _GLIBCXX_MEMORY_RESOURCE_H 31 #define _GLIBCXX_MEMORY_RESOURCE_H 1 32 33 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 #if __cplusplus >= 201703L 38 39 #include <new> // operator new(size_t, void*) 40 #include <cstddef> // size_t, max_align_t, byte 41 #include <bits/functexcept.h> // __throw_bad_array_new_length 42 #include <bits/uses_allocator.h> // allocator_arg_t, __use_alloc 43 #include <bits/uses_allocator_args.h> // uninitialized_construct_using_alloc 44 #include <ext/numeric_traits.h> // __int_traits 45 #include <debug/assertions.h> 46 47 #if ! __glibcxx_make_obj_using_allocator 48 # include <bits/utility.h> // index_sequence 49 # include <tuple> // tuple, forward_as_tuple 50 #endif 51 52 namespace std _GLIBCXX_VISIBILITY(default) 53 { 54 _GLIBCXX_BEGIN_NAMESPACE_VERSION 55 namespace pmr 56 { 57 /// Class `memory_resource` 58 /** 59 * @ingroup pmr 60 * @headerfile memory_resource 61 * @since C++17 62 */ 63 class memory_resource 64 { 65 static constexpr size_t _S_max_align = alignof(max_align_t); 66 67 public: 68 memory_resource() = default; 69 memory_resource(const memory_resource&) = default; 70 virtual ~memory_resource(); // key function 71 72 memory_resource& operator=(const memory_resource&) = default; 73 74 [[nodiscard]] 75 void* 76 allocate(size_t __bytes, size_t __alignment = _S_max_align) 77 __attribute__((__returns_nonnull__,__alloc_size__(2),__alloc_align__(3))) 78 { return ::operator new(__bytes, do_allocate(__bytes, __alignment)); } 79 80 void 81 deallocate(void* __p, size_t __bytes, size_t __alignment = _S_max_align) 82 __attribute__((__nonnull__)) 83 { return do_deallocate(__p, __bytes, __alignment); } 84 85 [[nodiscard]] 86 bool 87 is_equal(const memory_resource& __other) const noexcept 88 { return do_is_equal(__other); } 89 90 private: 91 virtual void* 92 do_allocate(size_t __bytes, size_t __alignment) = 0; 93 94 virtual void 95 do_deallocate(void* __p, size_t __bytes, size_t __alignment) = 0; 96 97 virtual bool 98 do_is_equal(const memory_resource& __other) const noexcept = 0; 99 }; 100 101 [[nodiscard]] 102 inline bool 103 operator==(const memory_resource& __a, const memory_resource& __b) noexcept 104 { return &__a == &__b || __a.is_equal(__b); } 105 106 #if __cpp_impl_three_way_comparison < 201907L 107 [[nodiscard]] 108 inline bool 109 operator!=(const memory_resource& __a, const memory_resource& __b) noexcept 110 { return !(__a == __b); } 111 #endif 112 113 // C++17 23.12.3 Class template polymorphic_allocator 114 115 /// Class template polymorphic_allocator 116 /** 117 * @ingroup pmr 118 * @headerfile memory_resource 119 * @since C++17 120 */ 121 template<typename _Tp> 122 class polymorphic_allocator 123 { 124 // _GLIBCXX_RESOLVE_LIB_DEFECTS 125 // 2975. Missing case for pair construction in polymorphic allocators 126 template<typename _Up> 127 struct __not_pair { using type = void; }; 128 129 template<typename _Up1, typename _Up2> 130 struct __not_pair<pair<_Up1, _Up2>> { }; 131 132 public: 133 using value_type = _Tp; 134 135 polymorphic_allocator() noexcept 136 { 137 extern memory_resource* get_default_resource() noexcept 138 __attribute__((__returns_nonnull__)); 139 _M_resource = get_default_resource(); 140 } 141 142 polymorphic_allocator(memory_resource* __r) noexcept 143 __attribute__((__nonnull__)) 144 : _M_resource(__r) 145 { _GLIBCXX_DEBUG_ASSERT(__r); } 146 147 polymorphic_allocator(const polymorphic_allocator& __other) = default; 148 149 template<typename _Up> 150 polymorphic_allocator(const polymorphic_allocator<_Up>& __x) noexcept 151 : _M_resource(__x.resource()) 152 { } 153 154 polymorphic_allocator& 155 operator=(const polymorphic_allocator&) = delete; 156 157 [[nodiscard]] 158 _Tp* 159 allocate(size_t __n) 160 __attribute__((__returns_nonnull__)) 161 { 162 if ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Tp)) < __n) 163 std::__throw_bad_array_new_length(); 164 return static_cast<_Tp*>(_M_resource->allocate(__n * sizeof(_Tp), 165 alignof(_Tp))); 166 } 167 168 void 169 deallocate(_Tp* __p, size_t __n) noexcept 170 __attribute__((__nonnull__)) 171 { _M_resource->deallocate(__p, __n * sizeof(_Tp), alignof(_Tp)); } 172 173 #ifdef __glibcxx_polymorphic_allocator // >= C++20 174 [[nodiscard]] void* 175 allocate_bytes(size_t __nbytes, 176 size_t __alignment = alignof(max_align_t)) 177 { return _M_resource->allocate(__nbytes, __alignment); } 178 179 void 180 deallocate_bytes(void* __p, size_t __nbytes, 181 size_t __alignment = alignof(max_align_t)) 182 { _M_resource->deallocate(__p, __nbytes, __alignment); } 183 184 template<typename _Up> 185 [[nodiscard]] _Up* 186 allocate_object(size_t __n = 1) 187 { 188 if ((__gnu_cxx::__int_traits<size_t>::__max / sizeof(_Up)) < __n) 189 std::__throw_bad_array_new_length(); 190 return static_cast<_Up*>(allocate_bytes(__n * sizeof(_Up), 191 alignof(_Up))); 192 } 193 194 template<typename _Up> 195 void 196 deallocate_object(_Up* __p, size_t __n = 1) 197 { deallocate_bytes(__p, __n * sizeof(_Up), alignof(_Up)); } 198 199 template<typename _Up, typename... _CtorArgs> 200 [[nodiscard]] _Up* 201 new_object(_CtorArgs&&... __ctor_args) 202 { 203 _Up* __p = allocate_object<_Up>(); 204 __try 205 { 206 construct(__p, std::forward<_CtorArgs>(__ctor_args)...); 207 } 208 __catch (...) 209 { 210 deallocate_object(__p); 211 __throw_exception_again; 212 } 213 return __p; 214 } 215 216 template<typename _Up> 217 void 218 delete_object(_Up* __p) 219 { 220 __p->~_Up(); 221 deallocate_object(__p); 222 } 223 #endif // C++20 224 225 #if ! __glibcxx_make_obj_using_allocator // >= C++20 226 template<typename _Tp1, typename... _Args> 227 __attribute__((__nonnull__)) 228 typename __not_pair<_Tp1>::type 229 construct(_Tp1* __p, _Args&&... __args) 230 { 231 // _GLIBCXX_RESOLVE_LIB_DEFECTS 232 // 2969. polymorphic_allocator::construct() shouldn't pass resource() 233 using __use_tag 234 = std::__uses_alloc_t<_Tp1, polymorphic_allocator, _Args...>; 235 if constexpr (is_base_of_v<__uses_alloc0, __use_tag>) 236 ::new(__p) _Tp1(std::forward<_Args>(__args)...); 237 else if constexpr (is_base_of_v<__uses_alloc1_, __use_tag>) 238 ::new(__p) _Tp1(allocator_arg, *this, 239 std::forward<_Args>(__args)...); 240 else 241 ::new(__p) _Tp1(std::forward<_Args>(__args)..., *this); 242 } 243 244 template<typename _Tp1, typename _Tp2, 245 typename... _Args1, typename... _Args2> 246 __attribute__((__nonnull__)) 247 void 248 construct(pair<_Tp1, _Tp2>* __p, piecewise_construct_t, 249 tuple<_Args1...> __x, tuple<_Args2...> __y) 250 { 251 auto __x_tag = 252 __use_alloc<_Tp1, polymorphic_allocator, _Args1...>(*this); 253 auto __y_tag = 254 __use_alloc<_Tp2, polymorphic_allocator, _Args2...>(*this); 255 index_sequence_for<_Args1...> __x_i; 256 index_sequence_for<_Args2...> __y_i; 257 258 ::new(__p) pair<_Tp1, _Tp2>(piecewise_construct, 259 _S_construct_p(__x_tag, __x_i, __x), 260 _S_construct_p(__y_tag, __y_i, __y)); 261 } 262 263 template<typename _Tp1, typename _Tp2> 264 __attribute__((__nonnull__)) 265 void 266 construct(pair<_Tp1, _Tp2>* __p) 267 { this->construct(__p, piecewise_construct, tuple<>(), tuple<>()); } 268 269 template<typename _Tp1, typename _Tp2, typename _Up, typename _Vp> 270 __attribute__((__nonnull__)) 271 void 272 construct(pair<_Tp1, _Tp2>* __p, _Up&& __x, _Vp&& __y) 273 { 274 this->construct(__p, piecewise_construct, 275 std::forward_as_tuple(std::forward<_Up>(__x)), 276 std::forward_as_tuple(std::forward<_Vp>(__y))); 277 } 278 279 template <typename _Tp1, typename _Tp2, typename _Up, typename _Vp> 280 __attribute__((__nonnull__)) 281 void 282 construct(pair<_Tp1, _Tp2>* __p, const std::pair<_Up, _Vp>& __pr) 283 { 284 this->construct(__p, piecewise_construct, 285 std::forward_as_tuple(__pr.first), 286 std::forward_as_tuple(__pr.second)); 287 } 288 289 template<typename _Tp1, typename _Tp2, typename _Up, typename _Vp> 290 __attribute__((__nonnull__)) 291 void 292 construct(pair<_Tp1, _Tp2>* __p, pair<_Up, _Vp>&& __pr) 293 { 294 this->construct(__p, piecewise_construct, 295 std::forward_as_tuple(std::forward<_Up>(__pr.first)), 296 std::forward_as_tuple(std::forward<_Vp>(__pr.second))); 297 } 298 #else // make_obj_using_allocator 299 template<typename _Tp1, typename... _Args> 300 __attribute__((__nonnull__)) 301 void 302 construct(_Tp1* __p, _Args&&... __args) 303 { 304 std::uninitialized_construct_using_allocator(__p, *this, 305 std::forward<_Args>(__args)...); 306 } 307 #endif 308 309 template<typename _Up> 310 __attribute__((__nonnull__)) 311 void 312 destroy(_Up* __p) 313 { __p->~_Up(); } 314 315 polymorphic_allocator 316 select_on_container_copy_construction() const noexcept 317 { return polymorphic_allocator(); } 318 319 memory_resource* 320 resource() const noexcept 321 __attribute__((__returns_nonnull__)) 322 { return _M_resource; } 323 324 // _GLIBCXX_RESOLVE_LIB_DEFECTS 325 // 3683. operator== for polymorphic_allocator cannot deduce template arg 326 [[nodiscard]] 327 friend bool 328 operator==(const polymorphic_allocator& __a, 329 const polymorphic_allocator& __b) noexcept 330 { return *__a.resource() == *__b.resource(); } 331 332 #if __cpp_impl_three_way_comparison < 201907L 333 [[nodiscard]] 334 friend bool 335 operator!=(const polymorphic_allocator& __a, 336 const polymorphic_allocator& __b) noexcept 337 { return !(__a == __b); } 338 #endif 339 340 private: 341 #if ! __glibcxx_make_obj_using_allocator // >= C++20 342 using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>; 343 using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>; 344 345 template<typename _Ind, typename... _Args> 346 static tuple<_Args&&...> 347 _S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) 348 { return std::move(__t); } 349 350 template<size_t... _Ind, typename... _Args> 351 static tuple<allocator_arg_t, polymorphic_allocator, _Args&&...> 352 _S_construct_p(__uses_alloc1_ __ua, index_sequence<_Ind...>, 353 tuple<_Args...>& __t) 354 { 355 return { 356 allocator_arg, *__ua._M_a, std::get<_Ind>(std::move(__t))... 357 }; 358 } 359 360 template<size_t... _Ind, typename... _Args> 361 static tuple<_Args&&..., polymorphic_allocator> 362 _S_construct_p(__uses_alloc2_ __ua, index_sequence<_Ind...>, 363 tuple<_Args...>& __t) 364 { return { std::get<_Ind>(std::move(__t))..., *__ua._M_a }; } 365 #endif 366 367 memory_resource* _M_resource; 368 }; 369 370 template<typename _Tp1, typename _Tp2> 371 [[nodiscard]] 372 inline bool 373 operator==(const polymorphic_allocator<_Tp1>& __a, 374 const polymorphic_allocator<_Tp2>& __b) noexcept 375 { return *__a.resource() == *__b.resource(); } 376 377 #if __cpp_impl_three_way_comparison < 201907L 378 template<typename _Tp1, typename _Tp2> 379 [[nodiscard]] 380 inline bool 381 operator!=(const polymorphic_allocator<_Tp1>& __a, 382 const polymorphic_allocator<_Tp2>& __b) noexcept 383 { return !(__a == __b); } 384 #endif 385 386 } // namespace pmr 387 388 template<typename _Alloc> struct allocator_traits; 389 390 /// Partial specialization for `std::pmr::polymorphic_allocator` 391 /** 392 * @ingroup pmr 393 * @headerfile memory_resource 394 * @since C++17 395 */ 396 template<typename _Tp> 397 struct allocator_traits<pmr::polymorphic_allocator<_Tp>> 398 { 399 /// The allocator type 400 using allocator_type = pmr::polymorphic_allocator<_Tp>; 401 402 /// The allocated type 403 using value_type = _Tp; 404 405 /// The allocator's pointer type. 406 using pointer = _Tp*; 407 408 /// The allocator's const pointer type. 409 using const_pointer = const _Tp*; 410 411 /// The allocator's void pointer type. 412 using void_pointer = void*; 413 414 /// The allocator's const void pointer type. 415 using const_void_pointer = const void*; 416 417 /// The allocator's difference type 418 using difference_type = std::ptrdiff_t; 419 420 /// The allocator's size type 421 using size_type = std::size_t; 422 423 /** @{ 424 * A `polymorphic_allocator` does not propagate when a 425 * container is copied, moved, or swapped. 426 */ 427 using propagate_on_container_copy_assignment = false_type; 428 using propagate_on_container_move_assignment = false_type; 429 using propagate_on_container_swap = false_type; 430 431 static allocator_type 432 select_on_container_copy_construction(const allocator_type&) noexcept 433 { return allocator_type(); } 434 /// @} 435 436 /// Whether all instances of the allocator type compare equal. 437 using is_always_equal = false_type; 438 439 template<typename _Up> 440 using rebind_alloc = pmr::polymorphic_allocator<_Up>; 441 442 template<typename _Up> 443 using rebind_traits = allocator_traits<pmr::polymorphic_allocator<_Up>>; 444 445 /** 446 * @brief Allocate memory. 447 * @param __a An allocator. 448 * @param __n The number of objects to allocate space for. 449 * 450 * Calls `a.allocate(n)`. 451 */ 452 [[nodiscard]] static pointer 453 allocate(allocator_type& __a, size_type __n) 454 { return __a.allocate(__n); } 455 456 /** 457 * @brief Allocate memory. 458 * @param __a An allocator. 459 * @param __n The number of objects to allocate space for. 460 * @return Memory of suitable size and alignment for `n` objects 461 * of type `value_type`. 462 * 463 * The third parameter is ignored.. 464 * 465 * Returns `a.allocate(n)`. 466 */ 467 [[nodiscard]] static pointer 468 allocate(allocator_type& __a, size_type __n, const_void_pointer) 469 { return __a.allocate(__n); } 470 471 /** 472 * @brief Deallocate memory. 473 * @param __a An allocator. 474 * @param __p Pointer to the memory to deallocate. 475 * @param __n The number of objects space was allocated for. 476 * 477 * Calls `a.deallocate(p, n)`. 478 */ 479 static void 480 deallocate(allocator_type& __a, pointer __p, size_type __n) 481 { __a.deallocate(__p, __n); } 482 483 /** 484 * @brief Construct an object of type `_Up` 485 * @param __a An allocator. 486 * @param __p Pointer to memory of suitable size and alignment for 487 * an object of type `_Up`. 488 * @param __args Constructor arguments. 489 * 490 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` 491 * in C++11, C++14 and C++17. Changed in C++20 to call 492 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. 493 */ 494 template<typename _Up, typename... _Args> 495 static void 496 construct(allocator_type& __a, _Up* __p, _Args&&... __args) 497 { __a.construct(__p, std::forward<_Args>(__args)...); } 498 499 /** 500 * @brief Destroy an object of type `_Up` 501 * @param __a An allocator. 502 * @param __p Pointer to the object to destroy 503 * 504 * Calls `p->_Up()`. 505 */ 506 template<typename _Up> 507 static _GLIBCXX20_CONSTEXPR void 508 destroy(allocator_type&, _Up* __p) 509 noexcept(is_nothrow_destructible<_Up>::value) 510 { __p->~_Up(); } 511 512 /** 513 * @brief The maximum supported allocation size 514 * @return `numeric_limits<size_t>::max() / sizeof(value_type)` 515 */ 516 static _GLIBCXX20_CONSTEXPR size_type 517 max_size(const allocator_type&) noexcept 518 { return size_t(-1) / sizeof(value_type); } 519 }; 520 521 _GLIBCXX_END_NAMESPACE_VERSION 522 } // namespace std 523 524 #endif // C++17 525 #endif // _GLIBCXX_MEMORY_RESOURCE_H