[ADT] Add resize_for_overwrite method to SmallVector.

Analagous to the std::make_(unqiue|shared)_for_overwrite added in c++20.
If T is POD, and the container gets larger, any new values added wont be initialized.
This is useful when using SmallVector as a buffer where its planned to overwrite any potential new values added.
If T is not POD, `new (Storage) T` functions identically to `new (Storage) T()` so this will function identically to `resize(size_type)`.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D93532
This commit is contained in:
Nathan James 2020-12-22 17:18:59 +00:00
parent be85b3e432
commit 5d10b8ad59
No known key found for this signature in database
GPG Key ID: CC007AFCDA90AA5F
2 changed files with 37 additions and 2 deletions

View File

@ -460,7 +460,8 @@ public:
this->Size = 0;
}
void resize(size_type N) {
private:
template <bool ForOverwrite> void resizeImpl(size_type N) {
if (N < this->size()) {
this->destroy_range(this->begin()+N, this->end());
this->set_size(N);
@ -468,11 +469,20 @@ public:
if (this->capacity() < N)
this->grow(N);
for (auto I = this->end(), E = this->begin() + N; I != E; ++I)
new (&*I) T();
if (ForOverwrite)
new (&*I) T;
else
new (&*I) T();
this->set_size(N);
}
}
public:
void resize(size_type N) { resizeImpl<false>(N); }
/// Like resize, but \ref T is POD, the new values won't be initialized.
void resize_for_overwrite(size_type N) { resizeImpl<true>(N); }
void resize(size_type N, const T &NV) {
if (N == this->size())
return;

View File

@ -341,6 +341,31 @@ TYPED_TEST(SmallVectorTest, ResizeFillTest) {
this->assertValuesInOrder(this->theVector, 3u, 77, 77, 77);
}
TEST(SmallVectorTest, ResizeForOverwrite) {
{
// Heap allocated storage.
SmallVector<unsigned, 0> V;
V.push_back(5);
V.pop_back();
V.resize_for_overwrite(V.size() + 1);
EXPECT_EQ(5, V.back());
V.pop_back();
V.resize(V.size() + 1);
EXPECT_EQ(0, V.back());
}
{
// Inline storage.
SmallVector<unsigned, 2> V;
V.push_back(5);
V.pop_back();
V.resize_for_overwrite(V.size() + 1);
EXPECT_EQ(5, V.back());
V.pop_back();
V.resize(V.size() + 1);
EXPECT_EQ(0, V.back());
}
}
// Overflow past fixed size.
TYPED_TEST(SmallVectorTest, OverflowTest) {
SCOPED_TRACE("OverflowTest");