forked from boostorg/unordered
Implement insert_or_assign.
This commit is contained in:
@ -3704,6 +3704,27 @@ struct table_impl : boost::unordered::detail::table<Types>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Key, typename M>
|
||||||
|
emplace_return insert_or_assign_impl(
|
||||||
|
BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj)
|
||||||
|
{
|
||||||
|
std::size_t key_hash = this->hash(k);
|
||||||
|
node_pointer pos = this->find_node(key_hash, k);
|
||||||
|
|
||||||
|
if (pos) {
|
||||||
|
pos->value().second = boost::forward<M>(obj);
|
||||||
|
return emplace_return(iterator(pos), false);
|
||||||
|
} else {
|
||||||
|
return emplace_return(
|
||||||
|
iterator(this->resize_and_add_node(
|
||||||
|
boost::unordered::detail::func::construct_node_pair(
|
||||||
|
this->node_alloc(), boost::forward<Key>(k),
|
||||||
|
boost::forward<M>(obj)),
|
||||||
|
key_hash)),
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// Insert range methods
|
// Insert range methods
|
||||||
//
|
//
|
||||||
|
@ -342,6 +342,37 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
|||||||
return this->emplace_hint(hint, boost::move(x));
|
return this->emplace_hint(hint, boost::move(x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign(
|
||||||
|
key_type const& k, BOOST_FWD_REF(M) obj)
|
||||||
|
{
|
||||||
|
return table_.insert_or_assign_impl(k, boost::forward<M>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
iterator insert_or_assign(
|
||||||
|
const_iterator, key_type const& k, BOOST_FWD_REF(M) obj)
|
||||||
|
{
|
||||||
|
return table_.insert_or_assign_impl(k, boost::forward<M>(obj)).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
std::pair<iterator, bool> insert_or_assign(
|
||||||
|
BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||||
|
{
|
||||||
|
return table_.insert_or_assign_impl(
|
||||||
|
boost::move(k), boost::forward<M>(obj));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class M>
|
||||||
|
iterator insert_or_assign(
|
||||||
|
const_iterator, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj)
|
||||||
|
{
|
||||||
|
return table_
|
||||||
|
.insert_or_assign_impl(boost::move(k), boost::forward<M>(obj))
|
||||||
|
.first;
|
||||||
|
}
|
||||||
|
|
||||||
template <class InputIt> void insert(InputIt, InputIt);
|
template <class InputIt> void insert(InputIt, InputIt);
|
||||||
|
|
||||||
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)
|
||||||
|
@ -301,13 +301,18 @@ template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class X, class Key, class T>
|
template <class X, class Key, class T>
|
||||||
void unordered_map_functions(X&, Key const& k, T const&)
|
void unordered_map_functions(X&, Key const& k, T const& v)
|
||||||
{
|
{
|
||||||
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
|
typedef BOOST_DEDUCED_TYPENAME X::mapped_type mapped_type;
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||||
|
|
||||||
X a;
|
X a;
|
||||||
test::check_return_type<mapped_type>::equals_ref(a[k]);
|
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<mapped_type>::equals_ref(a.at(k));
|
||||||
|
test::check_return_type<std::pair<iterator, bool> >::equals(
|
||||||
|
a.insert_or_assign(k, v));
|
||||||
|
test::check_return_type<iterator>::equals(
|
||||||
|
a.insert_or_assign(a.begin(), k, v));
|
||||||
|
|
||||||
X const b = a;
|
X const b = a;
|
||||||
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
|
test::check_return_type<mapped_type const>::equals_ref(b.at(k));
|
||||||
|
@ -505,6 +505,138 @@ template <class X> void map_tests(X*, test::random_generator generator)
|
|||||||
test::check_equivalent_keys(x);
|
test::check_equivalent_keys(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class X> void map_tests2(X*, test::random_generator generator)
|
||||||
|
{
|
||||||
|
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||||
|
std::cerr << "insert_or_assign\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
|
||||||
|
std::pair<iterator, bool> r =
|
||||||
|
x.insert_or_assign(it->first, it->second);
|
||||||
|
BOOST_TEST(*r.first == *it);
|
||||||
|
|
||||||
|
tracker[it->first] = it->second;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker.compare(x);
|
||||||
|
test::check_equivalent_keys(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "insert_or_assign(begin)\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
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 r = x.insert_or_assign(x.begin(), it->first, it->second);
|
||||||
|
BOOST_TEST(*r == *it);
|
||||||
|
|
||||||
|
tracker[it->first] = it->second;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker.compare(x);
|
||||||
|
test::check_equivalent_keys(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "insert_or_assign(end)\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
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 r = x.insert_or_assign(x.end(), it->first, it->second);
|
||||||
|
BOOST_TEST(*r == *it);
|
||||||
|
|
||||||
|
tracker[it->first] = it->second;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker.compare(x);
|
||||||
|
test::check_equivalent_keys(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cerr << "insert_or_assign(last)\n";
|
||||||
|
|
||||||
|
{
|
||||||
|
test::check_instances check_;
|
||||||
|
|
||||||
|
X x;
|
||||||
|
test::ordered<X> tracker = test::create_ordered(x);
|
||||||
|
iterator last = x.begin();
|
||||||
|
|
||||||
|
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 r = x.insert_or_assign(last, it->first, it->second);
|
||||||
|
BOOST_TEST(*r == *it);
|
||||||
|
|
||||||
|
tracker[it->first] = it->second;
|
||||||
|
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);
|
||||||
|
|
||||||
|
last = r;
|
||||||
|
}
|
||||||
|
|
||||||
|
tracker.compare(x);
|
||||||
|
test::check_equivalent_keys(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Some tests for when the range's value type doesn't match the container's
|
// Some tests for when the range's value type doesn't match the container's
|
||||||
// value type.
|
// value type.
|
||||||
|
|
||||||
@ -600,6 +732,9 @@ UNORDERED_TEST(default_emplace_tests,
|
|||||||
UNORDERED_TEST(map_tests,
|
UNORDERED_TEST(map_tests,
|
||||||
((test_map))((default_generator)(generate_collisions)(limited_range)))
|
((test_map))((default_generator)(generate_collisions)(limited_range)))
|
||||||
|
|
||||||
|
UNORDERED_TEST(
|
||||||
|
map_tests2, ((test_map))((default_generator)(generate_collisions)))
|
||||||
|
|
||||||
UNORDERED_TEST(map_insert_range_test1,
|
UNORDERED_TEST(map_insert_range_test1,
|
||||||
((test_multimap_std_alloc)(test_map)(test_multimap))(
|
((test_multimap_std_alloc)(test_map)(test_multimap))(
|
||||||
(default_generator)(generate_collisions)(limited_range)))
|
(default_generator)(generate_collisions)(limited_range)))
|
||||||
|
Reference in New Issue
Block a user