From dd89c56c2ad8fe06db8fd199c7ff77c817f0111f Mon Sep 17 00:00:00 2001 From: Aaron Jacobs Date: Tue, 11 Apr 2023 17:54:53 -0700 Subject: inlined_vector: relax the requirements on the move-construction fast path. Don't require a trivial move constructor and trivial destructor. This excludes types that have declared themselves trivially relocatable by another means, like std::unique_ptr. Instead use "is trivially relocatable" directly, which includes all previous types as well as those that have opted in. PiperOrigin-RevId: 523557136 Change-Id: Icea2dbb8f36f99623308155f2e5b1edd8e5bd36b --- absl/container/inlined_vector.h | 36 ++++++++++-------------------------- 1 file changed, 10 insertions(+), 26 deletions(-) (limited to 'absl/container/inlined_vector.h') diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h index 36327ad1..9c3289a7 100644 --- a/absl/container/inlined_vector.h +++ b/absl/container/inlined_vector.h @@ -217,20 +217,12 @@ class InlinedVector { absl::allocator_is_nothrow::value || std::is_nothrow_move_constructible::value) : storage_(other.storage_.GetAllocator()) { - // Fast path: if the value type can be trivally move constructed and - // destroyed, and we know the allocator doesn't do anything fancy, then it's - // safe for us to simply adopt the contents of the storage for `other` and - // remove its own reference to them. It's as if we had individually + // Fast path: if the value type can be trivially relocated (i.e. moved from + // and destroyed), and we know the allocator doesn't do anything fancy, then + // it's safe for us to simply adopt the contents of the storage for `other` + // and remove its own reference to them. It's as if we had individually // move-constructed each value and then destroyed the original. - // - // TODO(b/274984172): a move construction followed by destroying the source - // is a "relocation" in the language of P1144R4. So actually the minimum - // condition we need here (in addition to the allocator) is "trivially - // relocatable". Relaxing this would allow using memcpy with types like - // std::unique_ptr that opt in to declaring themselves trivially relocatable - // despite not being trivially move-constructible and/oror destructible. - if (absl::is_trivially_move_constructible::value && - absl::is_trivially_destructible::value && + if (absl::is_trivially_relocatable::value && std::is_same>::value) { storage_.MemcpyFrom(other.storage_); other.storage_.SetInlinedSize(0); @@ -271,20 +263,12 @@ class InlinedVector { const allocator_type& allocator) noexcept(absl::allocator_is_nothrow::value) : storage_(allocator) { - // Fast path: if the value type can be trivally move constructed and - // destroyed and we know the allocator doesn't do anything fancy, then it's - // safe for us to simply adopt the contents of the storage for `other` and - // remove its own reference to them. It's as if we had individually + // Fast path: if the value type can be trivially relocated (i.e. moved from + // and destroyed), and we know the allocator doesn't do anything fancy, then + // it's safe for us to simply adopt the contents of the storage for `other` + // and remove its own reference to them. It's as if we had individually // move-constructed each value and then destroyed the original. - // - // TODO(b/274984172): a move construction followed by destroying the source - // is a "relocation" in the language of P1144R4. So actually the minimum - // condition we need here (in addition to the allocator) is "trivially - // relocatable". Relaxing this would allow using memcpy with types like - // std::unique_ptr that opt in to declaring themselves trivially relocatable - // despite not being trivially move-constructible and/oror destructible. - if (absl::is_trivially_move_constructible::value && - absl::is_trivially_destructible::value && + if (absl::is_trivially_relocatable::value && std::is_same>::value) { storage_.MemcpyFrom(other.storage_); other.storage_.SetInlinedSize(0); -- cgit v1.2.3