--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FOLLY_BASE_CONTAINER_TRAITS_H_
+#define FOLLY_BASE_CONTAINER_TRAITS_H_
+
+#include <folly/Traits.h>
+
+namespace folly {
+
+FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(container_emplace_back_traits, emplace_back);
+
+template <class Container, typename... Args>
+inline
+typename std::enable_if<
+ container_emplace_back_traits<Container, void(Args...)>::value>::type
+container_emplace_back_or_push_back(Container& container, Args&&... args) {
+ container.emplace_back(std::forward<Args>(args)...);
+}
+
+template <class Container, typename... Args>
+inline
+typename std::enable_if<
+ !container_emplace_back_traits<Container, void(Args...)>::value>::type
+container_emplace_back_or_push_back(Container& container, Args&&... args) {
+ using v = typename Container::value_type;
+ container.push_back(v(std::forward<Args>(args)...));
+}
+
+}
+
+#endif
Chrono.h \
ConcurrentSkipList.h \
ConcurrentSkipList-inl.h \
+ ContainerTraits.h \
Conv.h \
CpuId.h \
CPortability.h \
#include <boost/iterator/iterator_adaptor.hpp>
#include <folly/Portability.h>
+#include <folly/ContainerTraits.h>
/**
* Code that aids in storing data aligned on block (possibly cache-line)
Adaptor(const Adaptor&) = default;
Adaptor& operator=(const Adaptor&) = default;
- Adaptor(Adaptor&& other)
+ Adaptor(Adaptor&& other) noexcept
: c_(std::move(other.c_)),
lastCount_(other.lastCount_) {
other.lastCount_ = Node::kElementCount;
return c_.back().data()[lastCount_ - 1];
}
+ template <typename... Args>
+ void emplace_back(Args&&... args) {
+ new (allocate_back()) value_type(std::forward<Args>(args)...);
+ }
+
void push_back(value_type x) {
- if (lastCount_ == Node::kElementCount) {
- c_.push_back(Node());
- lastCount_ = 0;
- }
- c_.back().data()[lastCount_++] = std::move(x);
+ emplace_back(std::move(x));
}
void pop_back() {
}
private:
+ value_type* allocate_back() {
+ if (lastCount_ == Node::kElementCount) {
+ container_emplace_back_or_push_back(c_);
+ lastCount_ = 0;
+ }
+ return &c_.back().data()[lastCount_++];
+ }
+
static Node fullNode(const value_type& value) {
Node n;
std::fill(n.data(), n.data() + kElementsPerNode, value);
--- /dev/null
+/*
+ * Copyright 2015 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <folly/ContainerTraits.h>
+
+#include <gtest/gtest.h>
+
+using namespace std;
+using namespace folly;
+
+struct Node {
+ size_t copies = 0;
+ Node() noexcept {};
+ Node(const Node& n) noexcept { copies = n.copies; ++copies; }
+ Node(Node&& n) noexcept { swap(copies, n.copies); ++copies; }
+};
+
+template <class T>
+class VectorWrapper {
+public:
+ using value_type = T;
+ vector<T>& underlying;
+ explicit VectorWrapper(vector<T>& v) : underlying(v) {}
+ void push_back(const T& t) { underlying.push_back(t); }
+};
+
+TEST(ContainerTraits, WithoutEmplaceBack) {
+ vector<Node> v;
+ VectorWrapper<Node> vw(v);
+ container_emplace_back_or_push_back(vw);
+ EXPECT_EQ(1, v.at(0).copies);
+}
+
+TEST(ContainerTraits, WithEmplaceBack) {
+ vector<Node> v;
+ container_emplace_back_or_push_back(v);
+ EXPECT_EQ(0, v.at(0).copies);
+}
EXPECT_EQ(42, a[i]);
}
}
+
+TEST_F(IntAdaptorTest, SimpleEmplaceBack) {
+ for (int i = 0; i < n_; ++i) {
+ EXPECT_EQ((i == 0), a_.empty());
+ EXPECT_EQ(i, a_.size());
+ a_.emplace_back(i);
+ }
+ EXPECT_EQ(n_, a_.size());
+
+ int k = 0;
+ for (auto it = a_.begin(); it != a_.end(); ++it, ++k) {
+ EXPECT_EQ(k, a_[k]);
+ EXPECT_EQ(k, *it);
+ }
+ EXPECT_EQ(n_, k);
+
+ auto p = a_.move();
+ EXPECT_TRUE(a_.empty());
+ EXPECT_EQ(16, p.second);
+ EXPECT_TRUE(v_ == p.first);
+}