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 @@
#include <folly/Malloc.h>
#include <folly/Portability.h>
#include <folly/SmallLocks.h>
#include <folly/Traits.h>
#include <folly/portability/BitsFunctexcept.h>
#include <folly/portability/Constexpr.h>
#include <folly/portability/Malloc.h>
......@@ -393,8 +394,12 @@ class small_vector
constructImpl(il.begin(), il.end(), std::false_type());
}
explicit small_vector(size_type n, value_type const& t = value_type()) {
doConstruct(n, t);
explicit small_vector(size_type n) {
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>
......@@ -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);
this->setSize(n);
try {
detail::populateMemForward(data(), n,
[&] (void* p) { new (p) value_type(val); }
);
detail::populateMemForward(data(), n, std::forward<InitFunc>(func));
} catch (...) {
if (this->isExtern()) {
u.freeHeap();
......@@ -900,7 +904,7 @@ private:
// The true_type means we should forward to the size_t,value_type
// overload.
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) {
......
......@@ -832,3 +832,27 @@ TEST(small_vector, InputIterator) {
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