From 1d563f40da16d8858a03da8f5d99989eb636c572 Mon Sep 17 00:00:00 2001 From: Benjamin Kramer Date: Sat, 7 Feb 2015 16:41:02 +0000 Subject: [PATCH] SmallVector: Move emplace_back to SmallVectorImpl. This resolves the strange effect that emplace_back is only available when the type contained in the vector is not trivially copyable. llvm-svn: 228496 --- llvm/include/llvm/ADT/SmallVector.h | 90 +++++++++++++++++----------------- llvm/unittests/ADT/SmallVectorTest.cpp | 8 +++ 2 files changed, 53 insertions(+), 45 deletions(-) diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index da4ac10..af9bbb6 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -236,51 +236,6 @@ public: this->setEnd(this->end()-1); this->end()->~T(); } - -#if LLVM_HAS_VARIADIC_TEMPLATES - template void emplace_back(ArgTypes &&... Args) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) - this->grow(); - ::new ((void *)this->end()) T(std::forward(Args)...); - this->setEnd(this->end() + 1); - } -#else -private: - template void emplace_back_impl(Constructor construct) { - if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) - this->grow(); - construct((void *)this->end()); - this->setEnd(this->end() + 1); - } - -public: - void emplace_back() { - emplace_back_impl([](void *Mem) { ::new (Mem) T(); }); - } - template void emplace_back(T1 &&A1) { - emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward(A1)); }); - } - template void emplace_back(T1 &&A1, T2 &&A2) { - emplace_back_impl([&](void *Mem) { - ::new (Mem) T(std::forward(A1), std::forward(A2)); - }); - } - template - void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) { - T(std::forward(A1), std::forward(A2), std::forward(A3)); - emplace_back_impl([&](void *Mem) { - ::new (Mem) - T(std::forward(A1), std::forward(A2), std::forward(A3)); - }); - } - template - void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { - emplace_back_impl([&](void *Mem) { - ::new (Mem) T(std::forward(A1), std::forward(A2), - std::forward(A3), std::forward(A4)); - }); - } -#endif // LLVM_HAS_VARIADIC_TEMPLATES }; // Define this out-of-line to dissuade the C++ compiler from inlining it. @@ -677,6 +632,51 @@ public: return I; } +#if LLVM_HAS_VARIADIC_TEMPLATES + template void emplace_back(ArgTypes &&... Args) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + ::new ((void *)this->end()) T(std::forward(Args)...); + this->setEnd(this->end() + 1); + } +#else +private: + template void emplace_back_impl(Constructor construct) { + if (LLVM_UNLIKELY(this->EndX >= this->CapacityX)) + this->grow(); + construct((void *)this->end()); + this->setEnd(this->end() + 1); + } + +public: + void emplace_back() { + emplace_back_impl([](void *Mem) { ::new (Mem) T(); }); + } + template void emplace_back(T1 &&A1) { + emplace_back_impl([&](void *Mem) { ::new (Mem) T(std::forward(A1)); }); + } + template void emplace_back(T1 &&A1, T2 &&A2) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward(A1), std::forward(A2)); + }); + } + template + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3) { + T(std::forward(A1), std::forward(A2), std::forward(A3)); + emplace_back_impl([&](void *Mem) { + ::new (Mem) + T(std::forward(A1), std::forward(A2), std::forward(A3)); + }); + } + template + void emplace_back(T1 &&A1, T2 &&A2, T3 &&A3, T4 &&A4) { + emplace_back_impl([&](void *Mem) { + ::new (Mem) T(std::forward(A1), std::forward(A2), + std::forward(A3), std::forward(A4)); + }); + } +#endif // LLVM_HAS_VARIADIC_TEMPLATES + SmallVectorImpl &operator=(const SmallVectorImpl &RHS); SmallVectorImpl &operator=(SmallVectorImpl &&RHS); diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index f6e9bb9..170a30b 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -896,6 +896,14 @@ TEST(SmallVectorTest, EmplaceBack) { EXPECT_TRUE(V.back().A2.State == EAS_RValue); EXPECT_TRUE(V.back().A3.State == EAS_LValue); } + { + SmallVector V; + V.emplace_back(); + V.emplace_back(42); + EXPECT_EQ(2U, V.size()); + EXPECT_EQ(0, V[0]); + EXPECT_EQ(42, V[1]); + } } } // end namespace -- 2.7.4