Commit acbd8f4f authored by Dmitry Pleshkov's avatar Dmitry Pleshkov Committed by Facebook Github Bot

small_vector should not require a copy-ctr from its element type unless it needs it.

Summary:
Use default constructor directly, instead of copying the element introduced by default parameter value.
This behavior is compatible with `std::vector`.

Reviewed By: ot, bixue2010, luciang

Differential Revision: D4700611

fbshipit-source-id: d3bd82c46c2857f5abcbec5dd2a64aaa85eaefe4
parent ce56a16a
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include <folly/Malloc.h> #include <folly/Malloc.h>
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/SmallLocks.h> #include <folly/SmallLocks.h>
#include <folly/Traits.h>
#include <folly/portability/BitsFunctexcept.h> #include <folly/portability/BitsFunctexcept.h>
#include <folly/portability/Constexpr.h> #include <folly/portability/Constexpr.h>
#include <folly/portability/Malloc.h> #include <folly/portability/Malloc.h>
...@@ -393,8 +394,12 @@ class small_vector ...@@ -393,8 +394,12 @@ class small_vector
constructImpl(il.begin(), il.end(), std::false_type()); constructImpl(il.begin(), il.end(), std::false_type());
} }
explicit small_vector(size_type n, value_type const& t = value_type()) { explicit small_vector(size_type n) {
doConstruct(n, t); doConstruct(n, [&](void* p) { new (p) value_type(); });
}
small_vector(size_type n, value_type const& t) {
doConstruct(n, [&](void* p) { new (p) value_type(t); });
} }
template<class Arg> template<class Arg>
...@@ -882,13 +887,12 @@ private: ...@@ -882,13 +887,12 @@ private:
} }
} }
void doConstruct(size_type n, value_type const& val) { template <typename InitFunc>
void doConstruct(size_type n, InitFunc&& func) {
makeSize(n); makeSize(n);
this->setSize(n); this->setSize(n);
try { try {
detail::populateMemForward(data(), n, detail::populateMemForward(data(), n, std::forward<InitFunc>(func));
[&] (void* p) { new (p) value_type(val); }
);
} catch (...) { } catch (...) {
if (this->isExtern()) { if (this->isExtern()) {
u.freeHeap(); u.freeHeap();
...@@ -900,7 +904,7 @@ private: ...@@ -900,7 +904,7 @@ private:
// The true_type means we should forward to the size_t,value_type // The true_type means we should forward to the size_t,value_type
// overload. // overload.
void constructImpl(size_type n, value_type const& val, std::true_type) { void constructImpl(size_type n, value_type const& val, std::true_type) {
doConstruct(n, val); doConstruct(n, [&](void* p) { new (p) value_type(val); });
} }
void makeSize(size_type size, value_type* v = nullptr) { void makeSize(size_type size, value_type* v = nullptr) {
......
...@@ -832,3 +832,27 @@ TEST(small_vector, InputIterator) { ...@@ -832,3 +832,27 @@ TEST(small_vector, InputIterator) {
ASSERT_EQ(smallV[i], expected[i]); ASSERT_EQ(smallV[i], expected[i]);
} }
} }
TEST(small_vector, NoCopyCtor) {
struct Test {
Test() = default;
Test(const Test&) = delete;
Test(Test&&) = default;
int field = 42;
};
small_vector<Test> test(10);
ASSERT_EQ(test.size(), 10);
for (const auto& element : test) {
EXPECT_EQ(element.field, 42);
}
}
TEST(small_vector, ZeroInitializable) {
small_vector<int> test(10);
ASSERT_EQ(test.size(), 10);
for (const auto& element : test) {
EXPECT_EQ(element, 0);
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment