summaryrefslogtreecommitdiff
path: root/absl/container/internal
diff options
context:
space:
mode:
authorGravatar Arthur O'Dwyer <arthur.j.odwyer@gmail.com>2024-03-03 18:47:41 -0800
committerGravatar Copybara-Service <copybara-worker@google.com>2024-03-03 18:48:47 -0800
commit7bd9ff910d489658da58251de1317eb3f790a2c6 (patch)
tree554dff6206f81d6e788f4fbd10e629b3d89f1553 /absl/container/internal
parent7a4344511816e82234700795e7f2aaa80e85a119 (diff)
PR #1632: inlined_vector: Use trivial relocation for `erase`
Diffstat (limited to 'absl/container/internal')
-rw-r--r--absl/container/internal/inlined_vector.h30
1 files changed, 22 insertions, 8 deletions
diff --git a/absl/container/internal/inlined_vector.h b/absl/container/internal/inlined_vector.h
index 90a74dc7..a1575328 100644
--- a/absl/container/internal/inlined_vector.h
+++ b/absl/container/internal/inlined_vector.h
@@ -893,16 +893,30 @@ auto Storage<T, N, A>::Erase(ConstIterator<A> from,
std::distance(ConstIterator<A>(storage_view.data), from));
SizeType<A> erase_end_index = erase_index + erase_size;
- IteratorValueAdapter<A, MoveIterator<A>> move_values(
- MoveIterator<A>(storage_view.data + erase_end_index));
-
- AssignElements<A>(storage_view.data + erase_index, move_values,
- storage_view.size - erase_end_index);
+ // Fast path: if the value type is trivially relocatable and we know
+ // the allocator doesn't do anything fancy, then we know it is legal for us to
+ // simply destroy the elements in the "erasure window" (which cannot throw)
+ // and then memcpy downward to close the window.
+ if (absl::is_trivially_relocatable<ValueType<A>>::value &&
+ std::is_nothrow_destructible<ValueType<A>>::value &&
+ std::is_same<A, std::allocator<ValueType<A>>>::value) {
+ DestroyAdapter<A>::DestroyElements(
+ GetAllocator(), storage_view.data + erase_index, erase_size);
+ std::memmove(
+ reinterpret_cast<char*>(storage_view.data + erase_index),
+ reinterpret_cast<const char*>(storage_view.data + erase_end_index),
+ (storage_view.size - erase_end_index) * sizeof(ValueType<A>));
+ } else {
+ IteratorValueAdapter<A, MoveIterator<A>> move_values(
+ MoveIterator<A>(storage_view.data + erase_end_index));
- DestroyAdapter<A>::DestroyElements(
- GetAllocator(), storage_view.data + (storage_view.size - erase_size),
- erase_size);
+ AssignElements<A>(storage_view.data + erase_index, move_values,
+ storage_view.size - erase_end_index);
+ DestroyAdapter<A>::DestroyElements(
+ GetAllocator(), storage_view.data + (storage_view.size - erase_size),
+ erase_size);
+ }
SubtractSize(erase_size);
return Iterator<A>(storage_view.data + erase_index);
}