|
34 | 34 | #include <__memory/allocator.h>
|
35 | 35 | #include <__memory/allocator_traits.h>
|
36 | 36 | #include <__memory/compressed_pair.h>
|
| 37 | +#include <__memory/is_trivially_allocator_relocatable.h> |
37 | 38 | #include <__memory/noexcept_move_assign_container.h>
|
38 | 39 | #include <__memory/pointer_traits.h>
|
39 | 40 | #include <__memory/swap_allocator.h>
|
40 | 41 | #include <__memory/temp_value.h>
|
41 | 42 | #include <__memory/uninitialized_algorithms.h>
|
| 43 | +#include <__memory/uninitialized_relocate.h> |
42 | 44 | #include <__ranges/access.h>
|
43 | 45 | #include <__ranges/concepts.h>
|
44 | 46 | #include <__ranges/container_compatible_range.h>
|
@@ -515,8 +517,36 @@ class _LIBCPP_TEMPLATE_VIS vector {
|
515 | 517 | }
|
516 | 518 | #endif
|
517 | 519 |
|
518 |
| - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position); |
519 |
| - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last); |
| 520 | + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { |
| 521 | + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
| 522 | + __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); |
| 523 | + return erase(__position, __position + 1); |
| 524 | + } |
| 525 | + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __cfirst, const_iterator __clast) { |
| 526 | + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__cfirst <= __clast, "vector::erase(first, last) called with invalid range"); |
| 527 | + |
| 528 | + iterator __first = begin() + std::distance(cbegin(), __cfirst); |
| 529 | + iterator __last = begin() + std::distance(cbegin(), __clast); |
| 530 | + if (__first == __last) |
| 531 | + return __last; |
| 532 | + |
| 533 | + auto __n = std::distance(__first, __last); |
| 534 | + |
| 535 | + // If the value_type is nothrow move constructible, we destroy the range being erased and we |
| 536 | + // relocate the tail of the vector into the created gap. This is especially efficient if the |
| 537 | + // elements are trivially relocatable. Otherwise, we use the standard technique with move-assignments. |
| 538 | + if constexpr (is_nothrow_move_constructible<value_type>::value) { |
| 539 | + std::__allocator_destroy(this->__alloc_, __first, __last); |
| 540 | + std::__uninitialized_allocator_relocate(this->__alloc_, __last, end(), __first); |
| 541 | + } else { |
| 542 | + auto __new_end = std::move(__last, end(), __first); |
| 543 | + std::__allocator_destroy(this->__alloc_, __new_end, end()); |
| 544 | + } |
| 545 | + |
| 546 | + this->__end_ -= __n; |
| 547 | + __annotate_shrink(size() + __n); |
| 548 | + return __first; |
| 549 | + } |
520 | 550 |
|
521 | 551 | _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT {
|
522 | 552 | size_type __old_size = size();
|
@@ -1108,28 +1138,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline
|
1108 | 1138 | #endif
|
1109 | 1139 | }
|
1110 | 1140 |
|
1111 |
| -template <class _Tp, class _Allocator> |
1112 |
| -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator |
1113 |
| -vector<_Tp, _Allocator>::erase(const_iterator __position) { |
1114 |
| - _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
1115 |
| - __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); |
1116 |
| - difference_type __ps = __position - cbegin(); |
1117 |
| - pointer __p = this->__begin_ + __ps; |
1118 |
| - this->__destruct_at_end(std::move(__p + 1, this->__end_, __p)); |
1119 |
| - return __make_iter(__p); |
1120 |
| -} |
1121 |
| - |
1122 |
| -template <class _Tp, class _Allocator> |
1123 |
| -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator |
1124 |
| -vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { |
1125 |
| - _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range"); |
1126 |
| - pointer __p = this->__begin_ + (__first - begin()); |
1127 |
| - if (__first != __last) { |
1128 |
| - this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p)); |
1129 |
| - } |
1130 |
| - return __make_iter(__p); |
1131 |
| -} |
1132 |
| - |
1133 | 1141 | template <class _Tp, class _Allocator>
|
1134 | 1142 | _LIBCPP_CONSTEXPR_SINCE_CXX20 void
|
1135 | 1143 | vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) {
|
|
0 commit comments