diff --git a/public/amtl/am-vector.h b/public/amtl/am-vector.h index 2b0b8feb..4f01bb97 100644 --- a/public/amtl/am-vector.h +++ b/public/amtl/am-vector.h @@ -167,6 +167,14 @@ class Vector : public AllocPolicy return growIfNeeded(desired - length()); } + Vector &operator =(Moveable > other) { + data_ = other->data_; + nitems_ = other->nitems_; + maxsize_ = other->maxsize_; + other->reset(); + return *this; + } + private: // These are disallowed because they basically violate the failure handling // model for AllocPolicies and are also likely to have abysmal performance. @@ -186,10 +194,15 @@ class Vector : public AllocPolicy } bool moveUp(size_t at) { - assert(at < nitems_); - if (!append(Moveable(data_[nitems_ - 1]))) + // Note: we don't use append() here. Passing an element as a Moveable into + // insert() or append() can break, since the underlying storage could be + // reallocated, invalidating the Moveable reference. Instead, we inline + // the logic to append() to ensure growIfNeeded occurs before any + // references are taken. + if (!growIfNeeded(1)) return false; - + new (&data_[nitems_]) T(Moveable(data_[nitems_ - 1])); + nitems_++; for (size_t i = nitems_ - 2; i > at; i--) data_[i] = Moveable(data_[i - 1]); return true;