|
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> |
@@ -518,8 +520,41 @@ class _LIBCPP_TEMPLATE_VIS vector { |
518 | 520 | } |
519 | 521 | #endif |
520 | 522 |
|
521 | | - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position); |
522 | | - _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __first, const_iterator __last); |
| 523 | + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __position) { |
| 524 | + _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
| 525 | + __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); |
| 526 | + return erase(__position, __position + 1); |
| 527 | + } |
| 528 | + _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI iterator erase(const_iterator __cfirst, const_iterator __clast) { |
| 529 | + _LIBCPP_ASSERT_VALID_INPUT_RANGE(__cfirst <= __clast, "vector::erase(first, last) called with invalid range"); |
| 530 | + |
| 531 | + iterator __first = begin() + std::distance(cbegin(), __cfirst); |
| 532 | + iterator __last = begin() + std::distance(cbegin(), __clast); |
| 533 | + if (__first == __last) |
| 534 | + return __last; |
| 535 | + |
| 536 | + auto const __n = std::distance(__first, __last); |
| 537 | + |
| 538 | + // If the value_type is nothrow relocatable, we destroy the range being erased and we relocate the tail |
| 539 | + // of the vector into the created gap. This is especially efficient if the elements are trivially relocatable. |
| 540 | + // Otherwise, we use the standard technique with move-assignments. |
| 541 | + // |
| 542 | + // Note that we also require __is_replaceable here for backwards compatibility, because we used |
| 543 | + // to perform move-assignments unconditionally. If we didn't enforce that, we would no longer call |
| 544 | + // the assignment operator of types that have a funky operator= and expect it to be called in |
| 545 | + // vector::erase. |
| 546 | + if constexpr (__is_replaceable<value_type>::value && __is_nothrow_allocator_relocatable<_Allocator, value_type>::value) { |
| 547 | + std::__allocator_destroy(this->__alloc_, __first, __last); |
| 548 | + std::__uninitialized_allocator_relocate(this->__alloc_, __last, end(), __first); |
| 549 | + } else { |
| 550 | + auto __new_end = std::move(__last, end(), __first); |
| 551 | + std::__allocator_destroy(this->__alloc_, __new_end, end()); |
| 552 | + } |
| 553 | + |
| 554 | + this->__end_ -= __n; |
| 555 | + __annotate_shrink(size() + __n); |
| 556 | + return __first; |
| 557 | + } |
523 | 558 |
|
524 | 559 | _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void clear() _NOEXCEPT { |
525 | 560 | size_type __old_size = size(); |
@@ -1113,28 +1148,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 inline |
1113 | 1148 | #endif |
1114 | 1149 | } |
1115 | 1150 |
|
1116 | | -template <class _Tp, class _Allocator> |
1117 | | -_LIBCPP_CONSTEXPR_SINCE_CXX20 inline _LIBCPP_HIDE_FROM_ABI typename vector<_Tp, _Allocator>::iterator |
1118 | | -vector<_Tp, _Allocator>::erase(const_iterator __position) { |
1119 | | - _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS( |
1120 | | - __position != end(), "vector::erase(iterator) called with a non-dereferenceable iterator"); |
1121 | | - difference_type __ps = __position - cbegin(); |
1122 | | - pointer __p = this->__begin_ + __ps; |
1123 | | - this->__destruct_at_end(std::move(__p + 1, this->__end_, __p)); |
1124 | | - return __make_iter(__p); |
1125 | | -} |
1126 | | - |
1127 | | -template <class _Tp, class _Allocator> |
1128 | | -_LIBCPP_CONSTEXPR_SINCE_CXX20 typename vector<_Tp, _Allocator>::iterator |
1129 | | -vector<_Tp, _Allocator>::erase(const_iterator __first, const_iterator __last) { |
1130 | | - _LIBCPP_ASSERT_VALID_INPUT_RANGE(__first <= __last, "vector::erase(first, last) called with invalid range"); |
1131 | | - pointer __p = this->__begin_ + (__first - begin()); |
1132 | | - if (__first != __last) { |
1133 | | - this->__destruct_at_end(std::move(__p + (__last - __first), this->__end_, __p)); |
1134 | | - } |
1135 | | - return __make_iter(__p); |
1136 | | -} |
1137 | | - |
1138 | 1151 | template <class _Tp, class _Allocator> |
1139 | 1152 | _LIBCPP_CONSTEXPR_SINCE_CXX20 void |
1140 | 1153 | vector<_Tp, _Allocator>::__move_range(pointer __from_s, pointer __from_e, pointer __to) { |
|
0 commit comments