1 // Allocator traits -*- C++ -*- 2 3 // Copyright (C) 2011-2020 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 bits/alloc_traits.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{memory} 28 */ 29 30 #ifndef _ALLOC_TRAITS_H 31 #define _ALLOC_TRAITS_H 1 32 33 #include <bits/stl_construct.h> 34 #include <bits/memoryfwd.h> 35 #if __cplusplus >= 201103L 36 # include <bits/allocator.h> 37 # include <bits/ptr_traits.h> 38 # include <ext/numeric_traits.h> 39 #endif 40 41 namespace std _GLIBCXX_VISIBILITY(default) 42 { 43 _GLIBCXX_BEGIN_NAMESPACE_VERSION 44 45 #if __cplusplus >= 201103L 46 #define __cpp_lib_allocator_traits_is_always_equal 201411 47 48 struct __allocator_traits_base 49 { 50 template<typename _Tp, typename _Up, typename = void> 51 struct __rebind : __replace_first_arg<_Tp, _Up> { }; 52 53 template<typename _Tp, typename _Up> 54 struct __rebind<_Tp, _Up, 55 __void_t<typename _Tp::template rebind<_Up>::other>> 56 { using type = typename _Tp::template rebind<_Up>::other; }; 57 58 protected: 59 template<typename _Tp> 60 using __pointer = typename _Tp::pointer; 61 template<typename _Tp> 62 using __c_pointer = typename _Tp::const_pointer; 63 template<typename _Tp> 64 using __v_pointer = typename _Tp::void_pointer; 65 template<typename _Tp> 66 using __cv_pointer = typename _Tp::const_void_pointer; 67 template<typename _Tp> 68 using __pocca = typename _Tp::propagate_on_container_copy_assignment; 69 template<typename _Tp> 70 using __pocma = typename _Tp::propagate_on_container_move_assignment; 71 template<typename _Tp> 72 using __pocs = typename _Tp::propagate_on_container_swap; 73 template<typename _Tp> 74 using __equal = typename _Tp::is_always_equal; 75 }; 76 77 template<typename _Alloc, typename _Up> 78 using __alloc_rebind 79 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; 80 81 /** 82 * @brief Uniform interface to all allocator types. 83 * @ingroup allocators 84 */ 85 template<typename _Alloc> 86 struct allocator_traits : __allocator_traits_base 87 { 88 /// The allocator type 89 typedef _Alloc allocator_type; 90 /// The allocated type 91 typedef typename _Alloc::value_type value_type; 92 93 /** 94 * @brief The allocator's pointer type. 95 * 96 * @c Alloc::pointer if that type exists, otherwise @c value_type* 97 */ 98 using pointer = __detected_or_t<value_type*, __pointer, _Alloc>; 99 100 private: 101 // Select _Func<_Alloc> or pointer_traits<pointer>::rebind<_Tp> 102 template<template<typename> class _Func, typename _Tp, typename = void> 103 struct _Ptr 104 { 105 using type = typename pointer_traits<pointer>::template rebind<_Tp>; 106 }; 107 108 template<template<typename> class _Func, typename _Tp> 109 struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> 110 { 111 using type = _Func<_Alloc>; 112 }; 113 114 // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type 115 template<typename _A2, typename _PtrT, typename = void> 116 struct _Diff 117 { using type = typename pointer_traits<_PtrT>::difference_type; }; 118 119 template<typename _A2, typename _PtrT> 120 struct _Diff<_A2, _PtrT, __void_t<typename _A2::difference_type>> 121 { using type = typename _A2::difference_type; }; 122 123 // Select _A2::size_type or make_unsigned<_DiffT>::type 124 template<typename _A2, typename _DiffT, typename = void> 125 struct _Size : make_unsigned<_DiffT> { }; 126 127 template<typename _A2, typename _DiffT> 128 struct _Size<_A2, _DiffT, __void_t<typename _A2::size_type>> 129 { using type = typename _A2::size_type; }; 130 131 public: 132 /** 133 * @brief The allocator's const pointer type. 134 * 135 * @c Alloc::const_pointer if that type exists, otherwise 136 * <tt> pointer_traits<pointer>::rebind<const value_type> </tt> 137 */ 138 using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; 139 140 /** 141 * @brief The allocator's void pointer type. 142 * 143 * @c Alloc::void_pointer if that type exists, otherwise 144 * <tt> pointer_traits<pointer>::rebind<void> </tt> 145 */ 146 using void_pointer = typename _Ptr<__v_pointer, void>::type; 147 148 /** 149 * @brief The allocator's const void pointer type. 150 * 151 * @c Alloc::const_void_pointer if that type exists, otherwise 152 * <tt> pointer_traits<pointer>::rebind<const void> </tt> 153 */ 154 using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; 155 156 /** 157 * @brief The allocator's difference type 158 * 159 * @c Alloc::difference_type if that type exists, otherwise 160 * <tt> pointer_traits<pointer>::difference_type </tt> 161 */ 162 using difference_type = typename _Diff<_Alloc, pointer>::type; 163 164 /** 165 * @brief The allocator's size type 166 * 167 * @c Alloc::size_type if that type exists, otherwise 168 * <tt> make_unsigned<difference_type>::type </tt> 169 */ 170 using size_type = typename _Size<_Alloc, difference_type>::type; 171 172 /** 173 * @brief How the allocator is propagated on copy assignment 174 * 175 * @c Alloc::propagate_on_container_copy_assignment if that type exists, 176 * otherwise @c false_type 177 */ 178 using propagate_on_container_copy_assignment 179 = __detected_or_t<false_type, __pocca, _Alloc>; 180 181 /** 182 * @brief How the allocator is propagated on move assignment 183 * 184 * @c Alloc::propagate_on_container_move_assignment if that type exists, 185 * otherwise @c false_type 186 */ 187 using propagate_on_container_move_assignment 188 = __detected_or_t<false_type, __pocma, _Alloc>; 189 190 /** 191 * @brief How the allocator is propagated on swap 192 * 193 * @c Alloc::propagate_on_container_swap if that type exists, 194 * otherwise @c false_type 195 */ 196 using propagate_on_container_swap 197 = __detected_or_t<false_type, __pocs, _Alloc>; 198 199 /** 200 * @brief Whether all instances of the allocator type compare equal. 201 * 202 * @c Alloc::is_always_equal if that type exists, 203 * otherwise @c is_empty<Alloc>::type 204 */ 205 using is_always_equal 206 = __detected_or_t<typename is_empty<_Alloc>::type, __equal, _Alloc>; 207 208 template<typename _Tp> 209 using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; 210 template<typename _Tp> 211 using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; 212 213 private: 214 template<typename _Alloc2> 215 static constexpr auto 216 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) 217 -> decltype(__a.allocate(__n, __hint)) 218 { return __a.allocate(__n, __hint); } 219 220 template<typename _Alloc2> 221 static constexpr pointer 222 _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) 223 { return __a.allocate(__n); } 224 225 template<typename _Tp, typename... _Args> 226 struct __construct_helper 227 { 228 template<typename _Alloc2, 229 typename = decltype(std::declval<_Alloc2*>()->construct( 230 std::declval<_Tp*>(), std::declval<_Args>()...))> 231 static true_type __test(int); 232 233 template<typename> 234 static false_type __test(...); 235 236 using type = decltype(__test<_Alloc>(0)); 237 }; 238 239 template<typename _Tp, typename... _Args> 240 using __has_construct 241 = typename __construct_helper<_Tp, _Args...>::type; 242 243 template<typename _Tp, typename... _Args> 244 static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>> 245 _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) 246 noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) 247 { __a.construct(__p, std::forward<_Args>(__args)...); } 248 249 template<typename _Tp, typename... _Args> 250 static _GLIBCXX14_CONSTEXPR 251 _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, 252 is_constructible<_Tp, _Args...>>> 253 _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) 254 noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value) 255 { 256 #if __cplusplus <= 201703L 257 ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); 258 #else 259 std::construct_at(__p, std::forward<_Args>(__args)...); 260 #endif 261 } 262 263 template<typename _Alloc2, typename _Tp> 264 static _GLIBCXX14_CONSTEXPR auto 265 _S_destroy(_Alloc2& __a, _Tp* __p, int) 266 noexcept(noexcept(__a.destroy(__p))) 267 -> decltype(__a.destroy(__p)) 268 { __a.destroy(__p); } 269 270 template<typename _Alloc2, typename _Tp> 271 static _GLIBCXX14_CONSTEXPR void 272 _S_destroy(_Alloc2&, _Tp* __p, ...) 273 noexcept(std::is_nothrow_destructible<_Tp>::value) 274 { std::_Destroy(__p); } 275 276 template<typename _Alloc2> 277 static constexpr auto 278 _S_max_size(_Alloc2& __a, int) 279 -> decltype(__a.max_size()) 280 { return __a.max_size(); } 281 282 template<typename _Alloc2> 283 static constexpr size_type 284 _S_max_size(_Alloc2&, ...) 285 { 286 // _GLIBCXX_RESOLVE_LIB_DEFECTS 287 // 2466. allocator_traits::max_size() default behavior is incorrect 288 return __gnu_cxx::__numeric_traits<size_type>::__max 289 / sizeof(value_type); 290 } 291 292 template<typename _Alloc2> 293 static constexpr auto 294 _S_select(_Alloc2& __a, int) 295 -> decltype(__a.select_on_container_copy_construction()) 296 { return __a.select_on_container_copy_construction(); } 297 298 template<typename _Alloc2> 299 static constexpr _Alloc2 300 _S_select(_Alloc2& __a, ...) 301 { return __a; } 302 303 public: 304 305 /** 306 * @brief Allocate memory. 307 * @param __a An allocator. 308 * @param __n The number of objects to allocate space for. 309 * 310 * Calls @c a.allocate(n) 311 */ 312 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer 313 allocate(_Alloc& __a, size_type __n) 314 { return __a.allocate(__n); } 315 316 /** 317 * @brief Allocate memory. 318 * @param __a An allocator. 319 * @param __n The number of objects to allocate space for. 320 * @param __hint Aid to locality. 321 * @return Memory of suitable size and alignment for @a n objects 322 * of type @c value_type 323 * 324 * Returns <tt> a.allocate(n, hint) </tt> if that expression is 325 * well-formed, otherwise returns @c a.allocate(n) 326 */ 327 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer 328 allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) 329 { return _S_allocate(__a, __n, __hint, 0); } 330 331 /** 332 * @brief Deallocate memory. 333 * @param __a An allocator. 334 * @param __p Pointer to the memory to deallocate. 335 * @param __n The number of objects space was allocated for. 336 * 337 * Calls <tt> a.deallocate(p, n) </tt> 338 */ 339 static _GLIBCXX20_CONSTEXPR void 340 deallocate(_Alloc& __a, pointer __p, size_type __n) 341 { __a.deallocate(__p, __n); } 342 343 /** 344 * @brief Construct an object of type `_Tp` 345 * @param __a An allocator. 346 * @param __p Pointer to memory of suitable size and alignment for Tp 347 * @param __args Constructor arguments. 348 * 349 * Calls <tt> __a.construct(__p, std::forward<Args>(__args)...) </tt> 350 * if that expression is well-formed, otherwise uses placement-new 351 * to construct an object of type @a _Tp at location @a __p from the 352 * arguments @a __args... 353 */ 354 template<typename _Tp, typename... _Args> 355 static _GLIBCXX20_CONSTEXPR auto 356 construct(_Alloc& __a, _Tp* __p, _Args&&... __args) 357 noexcept(noexcept(_S_construct(__a, __p, 358 std::forward<_Args>(__args)...))) 359 -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) 360 { _S_construct(__a, __p, std::forward<_Args>(__args)...); } 361 362 /** 363 * @brief Destroy an object of type @a _Tp 364 * @param __a An allocator. 365 * @param __p Pointer to the object to destroy 366 * 367 * Calls @c __a.destroy(__p) if that expression is well-formed, 368 * otherwise calls @c __p->~_Tp() 369 */ 370 template<typename _Tp> 371 static _GLIBCXX20_CONSTEXPR void 372 destroy(_Alloc& __a, _Tp* __p) 373 noexcept(noexcept(_S_destroy(__a, __p, 0))) 374 { _S_destroy(__a, __p, 0); } 375 376 /** 377 * @brief The maximum supported allocation size 378 * @param __a An allocator. 379 * @return @c __a.max_size() or @c numeric_limits<size_type>::max() 380 * 381 * Returns @c __a.max_size() if that expression is well-formed, 382 * otherwise returns @c numeric_limits<size_type>::max() 383 */ 384 static _GLIBCXX20_CONSTEXPR size_type 385 max_size(const _Alloc& __a) noexcept 386 { return _S_max_size(__a, 0); } 387 388 /** 389 * @brief Obtain an allocator to use when copying a container. 390 * @param __rhs An allocator. 391 * @return @c __rhs.select_on_container_copy_construction() or @a __rhs 392 * 393 * Returns @c __rhs.select_on_container_copy_construction() if that 394 * expression is well-formed, otherwise returns @a __rhs 395 */ 396 static _GLIBCXX20_CONSTEXPR _Alloc 397 select_on_container_copy_construction(const _Alloc& __rhs) 398 { return _S_select(__rhs, 0); } 399 }; 400 401 #if __cplusplus > 201703L 402 # define __cpp_lib_constexpr_dynamic_alloc 201907L 403 #endif 404 405 /// Partial specialization for std::allocator. 406 template<typename _Tp> 407 struct allocator_traits<allocator<_Tp>> 408 { 409 /// The allocator type 410 using allocator_type = allocator<_Tp>; 411 412 /// The allocated type 413 using value_type = _Tp; 414 415 /// The allocator's pointer type. 416 using pointer = _Tp*; 417 418 /// The allocator's const pointer type. 419 using const_pointer = const _Tp*; 420 421 /// The allocator's void pointer type. 422 using void_pointer = void*; 423 424 /// The allocator's const void pointer type. 425 using const_void_pointer = const void*; 426 427 /// The allocator's difference type 428 using difference_type = std::ptrdiff_t; 429 430 /// The allocator's size type 431 using size_type = std::size_t; 432 433 /// How the allocator is propagated on copy assignment 434 using propagate_on_container_copy_assignment = false_type; 435 436 /// How the allocator is propagated on move assignment 437 using propagate_on_container_move_assignment = true_type; 438 439 /// How the allocator is propagated on swap 440 using propagate_on_container_swap = false_type; 441 442 /// Whether all instances of the allocator type compare equal. 443 using is_always_equal = true_type; 444 445 template<typename _Up> 446 using rebind_alloc = allocator<_Up>; 447 448 template<typename _Up> 449 using rebind_traits = allocator_traits<allocator<_Up>>; 450 451 /** 452 * @brief Allocate memory. 453 * @param __a An allocator. 454 * @param __n The number of objects to allocate space for. 455 * 456 * Calls @c a.allocate(n) 457 */ 458 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer 459 allocate(allocator_type& __a, size_type __n) 460 { return __a.allocate(__n); } 461 462 /** 463 * @brief Allocate memory. 464 * @param __a An allocator. 465 * @param __n The number of objects to allocate space for. 466 * @param __hint Aid to locality. 467 * @return Memory of suitable size and alignment for @a n objects 468 * of type @c value_type 469 * 470 * Returns <tt> a.allocate(n, hint) </tt> 471 */ 472 _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer 473 allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) 474 { 475 #if __cplusplus <= 201703L 476 return __a.allocate(__n, __hint); 477 #else 478 return __a.allocate(__n); 479 #endif 480 } 481 482 /** 483 * @brief Deallocate memory. 484 * @param __a An allocator. 485 * @param __p Pointer to the memory to deallocate. 486 * @param __n The number of objects space was allocated for. 487 * 488 * Calls <tt> a.deallocate(p, n) </tt> 489 */ 490 static _GLIBCXX20_CONSTEXPR void 491 deallocate(allocator_type& __a, pointer __p, size_type __n) 492 { __a.deallocate(__p, __n); } 493 494 /** 495 * @brief Construct an object of type `_Up` 496 * @param __a An allocator. 497 * @param __p Pointer to memory of suitable size and alignment for 498 * an object of type `_Up`. 499 * @param __args Constructor arguments. 500 * 501 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` 502 * in C++11, C++14 and C++17. Changed in C++20 to call 503 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. 504 */ 505 template<typename _Up, typename... _Args> 506 static _GLIBCXX20_CONSTEXPR void 507 construct(allocator_type& __a __attribute__((__unused__)), _Up* __p, 508 _Args&&... __args) 509 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) 510 { 511 #if __cplusplus <= 201703L 512 __a.construct(__p, std::forward<_Args>(__args)...); 513 #else 514 std::construct_at(__p, std::forward<_Args>(__args)...); 515 #endif 516 } 517 518 /** 519 * @brief Destroy an object of type @a _Up 520 * @param __a An allocator. 521 * @param __p Pointer to the object to destroy 522 * 523 * Calls @c __a.destroy(__p). 524 */ 525 template<typename _Up> 526 static _GLIBCXX20_CONSTEXPR void 527 destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p) 528 noexcept(is_nothrow_destructible<_Up>::value) 529 { 530 #if __cplusplus <= 201703L 531 __a.destroy(__p); 532 #else 533 std::destroy_at(__p); 534 #endif 535 } 536 537 /** 538 * @brief The maximum supported allocation size 539 * @param __a An allocator. 540 * @return @c __a.max_size() 541 */ 542 static _GLIBCXX20_CONSTEXPR size_type 543 max_size(const allocator_type& __a __attribute__((__unused__))) noexcept 544 { 545 #if __cplusplus <= 201703L 546 return __a.max_size(); 547 #else 548 return size_t(-1) / sizeof(value_type); 549 #endif 550 } 551 552 /** 553 * @brief Obtain an allocator to use when copying a container. 554 * @param __rhs An allocator. 555 * @return @c __rhs 556 */ 557 static _GLIBCXX20_CONSTEXPR allocator_type 558 select_on_container_copy_construction(const allocator_type& __rhs) 559 { return __rhs; } 560 }; 561 562 /// Explicit specialization for std::allocator<void>. 563 template<> 564 struct allocator_traits<allocator<void>> 565 { 566 /// The allocator type 567 using allocator_type = allocator<void>; 568 569 /// The allocated type 570 using value_type = void; 571 572 /// The allocator's pointer type. 573 using pointer = void*; 574 575 /// The allocator's const pointer type. 576 using const_pointer = const void*; 577 578 /// The allocator's void pointer type. 579 using void_pointer = void*; 580 581 /// The allocator's const void pointer type. 582 using const_void_pointer = const void*; 583 584 /// The allocator's difference type 585 using difference_type = std::ptrdiff_t; 586 587 /// The allocator's size type 588 using size_type = std::size_t; 589 590 /// How the allocator is propagated on copy assignment 591 using propagate_on_container_copy_assignment = false_type; 592 593 /// How the allocator is propagated on move assignment 594 using propagate_on_container_move_assignment = true_type; 595 596 /// How the allocator is propagated on swap 597 using propagate_on_container_swap = false_type; 598 599 /// Whether all instances of the allocator type compare equal. 600 using is_always_equal = true_type; 601 602 template<typename _Up> 603 using rebind_alloc = allocator<_Up>; 604 605 template<typename _Up> 606 using rebind_traits = allocator_traits<allocator<_Up>>; 607 608 /// allocate is ill-formed for allocator<void> 609 static void* 610 allocate(allocator_type&, size_type, const void* = nullptr) = delete; 611 612 /// deallocate is ill-formed for allocator<void> 613 static void 614 deallocate(allocator_type&, void*, size_type) = delete; 615 616 /** 617 * @brief Construct an object of type `_Up` 618 * @param __a An allocator. 619 * @param __p Pointer to memory of suitable size and alignment for 620 * an object of type `_Up`. 621 * @param __args Constructor arguments. 622 * 623 * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` 624 * in C++11, C++14 and C++17. Changed in C++20 to call 625 * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. 626 */ 627 template<typename _Up, typename... _Args> 628 static _GLIBCXX20_CONSTEXPR void 629 construct(allocator_type&, _Up* __p, _Args&&... __args) 630 noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) 631 { 632 #if __cplusplus <= 201703L 633 ::new((void *)__p) _Up(std::forward<_Args>(__args)...); 634 #else 635 std::construct_at(__p, std::forward<_Args>(__args)...); 636 #endif 637 } 638 639 /** 640 * @brief Destroy an object of type `_Up` 641 * @param __a An allocator. 642 * @param __p Pointer to the object to destroy 643 * 644 * Invokes the destructor for `*__p`. 645 */ 646 template<typename _Up> 647 static _GLIBCXX20_CONSTEXPR void 648 destroy(allocator_type&, _Up* __p) 649 noexcept(is_nothrow_destructible<_Up>::value) 650 { std::_Destroy(__p); } 651 652 /// max_size is ill-formed for allocator<void> 653 static size_type 654 max_size(const allocator_type&) = delete; 655 656 /** 657 * @brief Obtain an allocator to use when copying a container. 658 * @param __rhs An allocator. 659 * @return `__rhs` 660 */ 661 static _GLIBCXX20_CONSTEXPR allocator_type 662 select_on_container_copy_construction(const allocator_type& __rhs) 663 { return __rhs; } 664 }; 665 666 #if __cplusplus < 201703L 667 template<typename _Alloc> 668 inline void 669 __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) 670 { __one = __two; } 671 672 template<typename _Alloc> 673 inline void 674 __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) 675 { } 676 #endif 677 678 template<typename _Alloc> 679 _GLIBCXX14_CONSTEXPR inline void 680 __alloc_on_copy(_Alloc& __one, const _Alloc& __two) 681 { 682 typedef allocator_traits<_Alloc> __traits; 683 typedef typename __traits::propagate_on_container_copy_assignment __pocca; 684 #if __cplusplus >= 201703L 685 if constexpr (__pocca::value) 686 __one = __two; 687 #else 688 __do_alloc_on_copy(__one, __two, __pocca()); 689 #endif 690 } 691 692 template<typename _Alloc> 693 constexpr _Alloc 694 __alloc_on_copy(const _Alloc& __a) 695 { 696 typedef allocator_traits<_Alloc> __traits; 697 return __traits::select_on_container_copy_construction(__a); 698 } 699 700 #if __cplusplus < 201703L 701 template<typename _Alloc> 702 inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) 703 { __one = std::move(__two); } 704 705 template<typename _Alloc> 706 inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) 707 { } 708 #endif 709 710 template<typename _Alloc> 711 _GLIBCXX14_CONSTEXPR inline void 712 __alloc_on_move(_Alloc& __one, _Alloc& __two) 713 { 714 typedef allocator_traits<_Alloc> __traits; 715 typedef typename __traits::propagate_on_container_move_assignment __pocma; 716 #if __cplusplus >= 201703L 717 if constexpr (__pocma::value) 718 __one = std::move(__two); 719 #else 720 __do_alloc_on_move(__one, __two, __pocma()); 721 #endif 722 } 723 724 #if __cplusplus < 201703L 725 template<typename _Alloc> 726 inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) 727 { 728 using std::swap; 729 swap(__one, __two); 730 } 731 732 template<typename _Alloc> 733 inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) 734 { } 735 #endif 736 737 template<typename _Alloc> 738 _GLIBCXX14_CONSTEXPR inline void 739 __alloc_on_swap(_Alloc& __one, _Alloc& __two) 740 { 741 typedef allocator_traits<_Alloc> __traits; 742 typedef typename __traits::propagate_on_container_swap __pocs; 743 #if __cplusplus >= 201703L 744 if constexpr (__pocs::value) 745 { 746 using std::swap; 747 swap(__one, __two); 748 } 749 #else 750 __do_alloc_on_swap(__one, __two, __pocs()); 751 #endif 752 } 753 754 template<typename _Alloc, typename _Tp, 755 typename _ValueT = __remove_cvref_t<typename _Alloc::value_type>, 756 typename = void> 757 struct __is_alloc_insertable_impl 758 : false_type 759 { }; 760 761 template<typename _Alloc, typename _Tp, typename _ValueT> 762 struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT, 763 __void_t<decltype(allocator_traits<_Alloc>::construct( 764 std::declval<_Alloc&>(), std::declval<_ValueT*>(), 765 std::declval<_Tp>()))>> 766 : true_type 767 { }; 768 769 // true if _Alloc::value_type is CopyInsertable into containers using _Alloc 770 // (might be wrong if _Alloc::construct exists but is not constrained, 771 // i.e. actually trying to use it would still be invalid. Use with caution.) 772 template<typename _Alloc> 773 struct __is_copy_insertable 774 : __is_alloc_insertable_impl<_Alloc, 775 typename _Alloc::value_type const&>::type 776 { }; 777 778 // std::allocator<_Tp> just requires CopyConstructible 779 template<typename _Tp> 780 struct __is_copy_insertable<allocator<_Tp>> 781 : is_copy_constructible<_Tp> 782 { }; 783 784 // true if _Alloc::value_type is MoveInsertable into containers using _Alloc 785 // (might be wrong if _Alloc::construct exists but is not constrained, 786 // i.e. actually trying to use it would still be invalid. Use with caution.) 787 template<typename _Alloc> 788 struct __is_move_insertable 789 : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type 790 { }; 791 792 // std::allocator<_Tp> just requires MoveConstructible 793 template<typename _Tp> 794 struct __is_move_insertable<allocator<_Tp>> 795 : is_move_constructible<_Tp> 796 { }; 797 798 // Trait to detect Allocator-like types. 799 template<typename _Alloc, typename = void> 800 struct __is_allocator : false_type { }; 801 802 template<typename _Alloc> 803 struct __is_allocator<_Alloc, 804 __void_t<typename _Alloc::value_type, 805 decltype(std::declval<_Alloc&>().allocate(size_t{}))>> 806 : true_type { }; 807 808 template<typename _Alloc> 809 using _RequireAllocator 810 = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; 811 812 template<typename _Alloc> 813 using _RequireNotAllocator 814 = typename enable_if<!__is_allocator<_Alloc>::value, _Alloc>::type; 815 #endif // C++11 816 817 /** 818 * Destroy a range of objects using the supplied allocator. For 819 * non-default allocators we do not optimize away invocation of 820 * destroy() even if _Tp has a trivial destructor. 821 */ 822 823 template<typename _ForwardIterator, typename _Allocator> 824 void 825 _Destroy(_ForwardIterator __first, _ForwardIterator __last, 826 _Allocator& __alloc) 827 { 828 for (; __first != __last; ++__first) 829 #if __cplusplus < 201103L 830 __alloc.destroy(std::__addressof(*__first)); 831 #else 832 allocator_traits<_Allocator>::destroy(__alloc, 833 std::__addressof(*__first)); 834 #endif 835 } 836 837 template<typename _ForwardIterator, typename _Tp> 838 inline void 839 _Destroy(_ForwardIterator __first, _ForwardIterator __last, 840 allocator<_Tp>&) 841 { 842 _Destroy(__first, __last); 843 } 844 845 _GLIBCXX_END_NAMESPACE_VERSION 846 } // namespace std 847 #endif // _ALLOC_TRAITS_H 848