Commit 719b2df9 authored by Philipp Unterbrunner's avatar Philipp Unterbrunner Committed by Facebook Github Bot

Added folly::hint_emplace_iterator to folly/Iterator.h

Summary:
In contrast to Container::insert(), for any STL container class, Container::emplace() does not have an overload that takes a Container::iterator as its first parameter. (The reason is to prevent ambiguity with respect to target class constructor parameters.) Instead, container classes have a separate emplace_hint() function.
Because of this separation, folly::emplace_iterator would fail to perform hinted emplacement in constructs where std::insert_iterator would perform hinted insertion.
This diff adds a new class, folly::hint_emplace_iterator(), and corresponding convenience function, folly::hint_emplacer(), which calls Container::emplace_hint() rather than Container::emplace().
It would have been trivial to copy&paste the existing folly::emplace_iterator class and simply replace the emplace() call with emplace_hint(), but I did not like the large amount of code repetition. So I decided to do some refactoring and move the emplace()/emplace_hint()/emplace_front()/emplace_back() calls into separate trait classes, and replace emplace_iterator()/hint_emplace_iterator()/front_emplace_iterator()/back_emplace_iterator() with suitable type aliases.

Reviewed By: yfeldblum

Differential Revision: D5097860

fbshipit-source-id: c0b733131a0d0d21fc0a8b08ad655142c6a41c19
parent a7001e5c
This diff is collapsed.
......@@ -19,9 +19,12 @@
#include <cstddef>
#include <deque>
#include <functional>
#include <map>
#include <set>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#include <folly/Iterator.h>
#include <folly/portability/GTest.h>
......@@ -219,6 +222,60 @@ TEST(EmplaceIterator, BackEmplacerTest) {
}
}
/**
* Basic tests for folly::hint_emplace_iterator.
*/
TEST(EmplaceIterator, HintEmplacerTest) {
{
init_counters();
std::map<int, Object> m;
auto it = hint_emplacer(m, m.end());
it = make_emplace_args(
std::piecewise_construct,
std::forward_as_tuple(0),
std::forward_as_tuple(0));
it = make_emplace_args(
std::piecewise_construct,
std::forward_as_tuple(1),
std::forward_as_tuple(0, 0));
it = make_emplace_args(
std::piecewise_construct,
std::forward_as_tuple(2),
std::forward_as_tuple(Object{}));
ASSERT_EQ(m.size(), 3);
EXPECT_EQ(gDefaultCtrCnt, 1);
EXPECT_EQ(gCopyCtrCnt, 0);
EXPECT_EQ(gMoveCtrCnt, 1);
EXPECT_EQ(gExplicitCtrCnt, 1);
EXPECT_EQ(gMultiargCtrCnt, 1);
EXPECT_EQ(gCopyOpCnt, 0);
EXPECT_EQ(gMoveOpCnt, 0);
EXPECT_EQ(gConvertOpCnt, 0);
}
{
struct O {
explicit O(int i) : i(i) {}
bool operator<(const O& other) const {
return i < other.i;
}
bool operator==(const O& other) const {
return i == other.i;
}
int i;
};
std::vector<int> v1 = {0, 1, 2, 3, 4};
std::vector<int> v2 = {0, 2, 4};
std::set<O> diff;
std::set_difference(
v1.begin(),
v1.end(),
v2.begin(),
v2.end(),
hint_emplacer(diff, diff.end()));
ASSERT_EQ(diff, std::set<O>({O(1), O(3)}));
}
}
/**
* Test std::copy() with explicit conversion. This would not compile with a
* std::back_insert_iterator, because the constructor of Object that takes a
......
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