summaryrefslogtreecommitdiff
path: root/absl/container/inlined_vector.h
diff options
context:
space:
mode:
authorGravatar Abseil Team <absl-team@google.com>2022-10-12 05:52:24 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2022-10-12 05:53:14 -0700
commit90965f4c9662a73f2eb9c345b3a5431f40fd86d3 (patch)
tree64107a9f2f6eb2baf62aa1b89d4c9c13c0ae6aa8 /absl/container/inlined_vector.h
parent91b7cd600a34cbd318c87196d7147c41197f8161 (diff)
`absl::InlinedVector` supports move assignment with non-assignable types.
PiperOrigin-RevId: 480601268 Change-Id: I5a639da57b79ae600387c81e662d5c1542b2bf99
Diffstat (limited to 'absl/container/inlined_vector.h')
-rw-r--r--absl/container/inlined_vector.h61
1 files changed, 49 insertions, 12 deletions
diff --git a/absl/container/inlined_vector.h b/absl/container/inlined_vector.h
index 60f12460..10b1896b 100644
--- a/absl/container/inlined_vector.h
+++ b/absl/container/inlined_vector.h
@@ -52,6 +52,7 @@
#include "absl/base/port.h"
#include "absl/container/internal/inlined_vector.h"
#include "absl/memory/memory.h"
+#include "absl/meta/type_traits.h"
namespace absl {
ABSL_NAMESPACE_BEGIN
@@ -77,6 +78,8 @@ class InlinedVector {
using MoveIterator = inlined_vector_internal::MoveIterator<TheA>;
template <typename TheA>
using IsMemcpyOk = inlined_vector_internal::IsMemcpyOk<TheA>;
+ template <typename TheA>
+ using IsMoveAssignOk = inlined_vector_internal::IsMoveAssignOk<TheA>;
template <typename TheA, typename Iterator>
using IteratorValueAdapter =
@@ -94,6 +97,15 @@ class InlinedVector {
using DisableIfAtLeastForwardIterator = absl::enable_if_t<
!inlined_vector_internal::IsAtLeastForwardIterator<Iterator>::value, int>;
+ struct MemcpyPolicy {};
+ struct ElementwiseAssignPolicy {};
+ struct ElementwiseConstructPolicy {};
+
+ using MoveAssignmentPolicy = absl::conditional_t<
+ IsMemcpyOk<A>::value, MemcpyPolicy,
+ absl::conditional_t<IsMoveAssignOk<A>::value, ElementwiseAssignPolicy,
+ ElementwiseConstructPolicy>>;
+
public:
using allocator_type = A;
using value_type = inlined_vector_internal::ValueType<A>;
@@ -486,18 +498,7 @@ class InlinedVector {
// unspecified state.
InlinedVector& operator=(InlinedVector&& other) {
if (ABSL_PREDICT_TRUE(this != std::addressof(other))) {
- if (IsMemcpyOk<A>::value || other.storage_.GetIsAllocated()) {
- inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
- storage_.GetAllocator(), data(), size());
- storage_.DeallocateIfAllocated();
- storage_.MemcpyFrom(other.storage_);
-
- other.storage_.SetInlinedSize(0);
- } else {
- storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
- MoveIterator<A>(other.storage_.GetInlinedData())),
- other.size());
- }
+ MoveAssignment(MoveAssignmentPolicy{}, std::move(other));
}
return *this;
@@ -773,6 +774,42 @@ class InlinedVector {
template <typename H, typename TheT, size_t TheN, typename TheA>
friend H AbslHashValue(H h, const absl::InlinedVector<TheT, TheN, TheA>& a);
+ void MoveAssignment(MemcpyPolicy, InlinedVector&& other) {
+ inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
+ storage_.GetAllocator(), data(), size());
+ storage_.DeallocateIfAllocated();
+ storage_.MemcpyFrom(other.storage_);
+
+ other.storage_.SetInlinedSize(0);
+ }
+
+ void MoveAssignment(ElementwiseAssignPolicy, InlinedVector&& other) {
+ if (other.storage_.GetIsAllocated()) {
+ MoveAssignment(MemcpyPolicy{}, std::move(other));
+ } else {
+ storage_.Assign(IteratorValueAdapter<A, MoveIterator<A>>(
+ MoveIterator<A>(other.storage_.GetInlinedData())),
+ other.size());
+ }
+ }
+
+ void MoveAssignment(ElementwiseConstructPolicy, InlinedVector&& other) {
+ if (other.storage_.GetIsAllocated()) {
+ MoveAssignment(MemcpyPolicy{}, std::move(other));
+ } else {
+ inlined_vector_internal::DestroyAdapter<A>::DestroyElements(
+ storage_.GetAllocator(), data(), size());
+ storage_.DeallocateIfAllocated();
+
+ IteratorValueAdapter<A, MoveIterator<A>> other_values(
+ MoveIterator<A>(other.storage_.GetInlinedData()));
+ inlined_vector_internal::ConstructElements<A>(
+ storage_.GetAllocator(), storage_.GetInlinedData(), other_values,
+ other.storage_.GetSize());
+ storage_.SetInlinedSize(other.storage_.GetSize());
+ }
+ }
+
Storage storage_;
};