Implement try_emplace

This commit is contained in:
Daniel James
2017-02-27 03:59:02 +00:00
parent 958d206bb6
commit 5f5f8ef1e4
5 changed files with 527 additions and 17 deletions

View File

@@ -309,10 +309,21 @@ void unordered_map_functions(X&, Key const& k, T const& v)
X a;
test::check_return_type<mapped_type>::equals_ref(a[k]);
test::check_return_type<mapped_type>::equals_ref(a.at(k));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.try_emplace(k, v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.try_emplace(rvalue(k), v));
test::check_return_type<iterator>::equals(a.try_emplace(a.begin(), k, v));
test::check_return_type<iterator>::equals(
a.try_emplace(a.begin(), rvalue(k), v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.insert_or_assign(k, v));
test::check_return_type<std::pair<iterator, bool> >::equals(
a.insert_or_assign(rvalue(k), v));
test::check_return_type<iterator>::equals(
a.insert_or_assign(a.begin(), k, v));
test::check_return_type<iterator>::equals(
a.insert_or_assign(a.begin(), rvalue(k), v));
X const b = a;
test::check_return_type<mapped_type const>::equals_ref(b.at(k));

View File

@@ -465,6 +465,55 @@ UNORDERED_AUTO_TEST(emplace_multimap)
BOOST_TEST_EQ(check_.instances(), 20);
BOOST_TEST_EQ(check_.constructions(), 20);
}
UNORDERED_AUTO_TEST(try_emplace)
{
test::check_instances check_;
typedef boost::unordered_map<int, emplace_value> container;
typedef container::iterator iterator;
typedef std::pair<iterator, bool> return_type;
container x(10);
return_type r1, r2, r3;
int k1 = 3;
emplace_value m1(414, "grr");
r1 = x.try_emplace(3, 414, "grr");
BOOST_TEST(r1.second);
BOOST_TEST(r1.first->first == k1);
BOOST_TEST(r1.first->second == m1);
BOOST_TEST_EQ(x.size(), 1u);
BOOST_TEST_EQ(check_.instances(), 2);
BOOST_TEST_EQ(check_.constructions(), 2);
int k2 = 10;
emplace_value m2(25, "", 'z');
r2 = x.try_emplace(10, 25, std::string(""), 'z');
BOOST_TEST(r2.second);
BOOST_TEST(r2.first->first == k2);
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(x.find(k1)->second == m1);
BOOST_TEST(x.find(k2)->second == m2);
r3 = x.try_emplace(k2, 68, "jfeoj", 'p', 49309, 2323);
BOOST_TEST(!r3.second);
BOOST_TEST(r3.first == r2.first);
BOOST_TEST(r3.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
BOOST_TEST_EQ(check_.instances(), 4);
BOOST_TEST_EQ(check_.constructions(), 4);
BOOST_TEST(r2.first == x.try_emplace(r2.first, k2, 808709, "what"));
BOOST_TEST(
r2.first ==
x.try_emplace(r2.first, k2, 10, "xxx", 'a', 4, 5, 6, 7, 8, 9, 10));
BOOST_TEST(r2.first->second == m2);
BOOST_TEST_EQ(x.size(), 2u);
}
}
RUN_TESTS()

View File

@@ -637,6 +637,171 @@ template <class X> void map_tests2(X*, test::random_generator generator)
}
}
template <class X> void try_emplace_tests(X*, test::random_generator generator)
{
std::cerr << "try_emplace(key, value)\n";
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
iterator pos = x.find(it->first);
bool found = pos != x.end();
std::pair<typename X::iterator, bool> r =
x.try_emplace(it->first, it->second);
if (found) {
BOOST_TEST(pos == r.first);
BOOST_TEST(!r.second);
} else {
BOOST_TEST(r.second);
}
BOOST_TEST_EQ(r.first->first, it->first);
BOOST_TEST_EQ(r.first->second, it->second);
tracker.insert(*it);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
std::cerr << "try_emplace(begin(), key, value)\n";
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
iterator pos = x.find(it->first);
bool found = pos != x.end();
typename X::iterator r =
x.try_emplace(r.begin(), it->first, it->second);
if (found) {
BOOST_TEST(pos == r);
}
BOOST_TEST_EQ(r->first, it->first);
BOOST_TEST_EQ(r->second, it->second);
tracker.insert(*it);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
std::cerr << "try_emplace(end(), key, value)\n";
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
iterator pos = x.find(it->first);
bool found = pos != x.end();
typename X::iterator r =
x.try_emplace(r.end(), it->first, it->second);
if (found) {
BOOST_TEST(pos == r);
}
BOOST_TEST_EQ(r->first, it->first);
BOOST_TEST_EQ(r->second, it->second);
tracker.insert(*it);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
std::cerr << "try_emplace(pos, key, value)\n";
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
{
test::check_instances check_;
X x;
test::ordered<X> tracker = test::create_ordered(x);
test::random_values<X> v(1000, generator);
for (BOOST_DEDUCED_TYPENAME test::random_values<X>::iterator it =
v.begin();
it != v.end(); ++it) {
BOOST_DEDUCED_TYPENAME X::size_type old_bucket_count =
x.bucket_count();
float b = x.max_load_factor();
iterator pos = x.find(it->first);
bool found = pos != x.end();
typename X::iterator r = x.try_emplace(pos, it->first, it->second);
if (found) {
BOOST_TEST(pos == r);
}
BOOST_TEST_EQ(r->first, it->first);
BOOST_TEST_EQ(r->second, it->second);
tracker.insert(*it);
tracker.compare_key(x, *it);
if (static_cast<double>(x.size()) <
b * static_cast<double>(old_bucket_count))
BOOST_TEST(x.bucket_count() == old_bucket_count);
}
test::check_equivalent_keys(x);
}
}
// Some tests for when the range's value type doesn't match the container's
// value type.
@@ -876,6 +1041,10 @@ UNORDERED_AUTO_TEST(map_emplace_test)
x.emplace(2, 3);
BOOST_TEST(
x.find(2) != x.end() && x.find(2)->second == overloaded_constructor(3));
x.try_emplace(5);
BOOST_TEST(
x.find(5) != x.end() && x.find(5)->second == overloaded_constructor());
}
UNORDERED_AUTO_TEST(set_emplace_test)
@@ -954,6 +1123,23 @@ UNORDERED_AUTO_TEST(map_emplace_test2)
BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() &&
x.find(overloaded_constructor(9, 3, 1))->second ==
overloaded_constructor(10));
x.clear();
x.try_emplace(overloaded_constructor());
BOOST_TEST(
x.find(overloaded_constructor()) != x.end() &&
x.find(overloaded_constructor())->second == overloaded_constructor());
x.try_emplace(1);
BOOST_TEST(
x.find(overloaded_constructor(1)) != x.end() &&
x.find(overloaded_constructor(1))->second == overloaded_constructor());
x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6);
BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() &&
x.find(overloaded_constructor(2, 3))->second ==
overloaded_constructor(4, 5, 6));
}
UNORDERED_AUTO_TEST(set_emplace_test2)