forked from boostorg/unordered
Support node_handle
This commit is contained in:
@@ -19,18 +19,21 @@
|
||||
|
||||
// Explicit instantiation to catch compile-time errors
|
||||
|
||||
template class boost::unordered_map<int, int, boost::hash<int>,
|
||||
std::equal_to<int>, test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multimap<int const, int const, boost::hash<int>,
|
||||
#define INSTANTIATE(type) \
|
||||
template class boost::unordered::detail::instantiate_##type
|
||||
|
||||
INSTANTIATE(map)<int, int, boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
INSTANTIATE(multimap)<int const, int const, boost::hash<int>,
|
||||
std::equal_to<int>, test::minimal::allocator<int> >;
|
||||
|
||||
template class boost::unordered_map<test::minimal::assignable const,
|
||||
INSTANTIATE(map)<test::minimal::assignable const,
|
||||
test::minimal::default_assignable const,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multimap<test::minimal::assignable,
|
||||
test::minimal::assignable, test::minimal::hash<test::minimal::assignable>,
|
||||
INSTANTIATE(multimap)<test::minimal::assignable, test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<int> >;
|
||||
|
||||
|
||||
@@ -19,16 +19,19 @@
|
||||
|
||||
// Explicit instantiation to catch compile-time errors
|
||||
|
||||
template class boost::unordered_set<int, boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multiset<int const, boost::hash<int>,
|
||||
std::equal_to<int>, test::minimal::allocator<int> >;
|
||||
#define INSTANTIATE(type) \
|
||||
template class boost::unordered::detail::instantiate_##type
|
||||
|
||||
template class boost::unordered_set<test::minimal::assignable const,
|
||||
INSTANTIATE(set)<int, boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
INSTANTIATE(multiset)<int const, boost::hash<int>, std::equal_to<int>,
|
||||
test::minimal::allocator<int> >;
|
||||
|
||||
INSTANTIATE(set)<test::minimal::assignable const,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<int> >;
|
||||
template class boost::unordered_multiset<test::minimal::assignable,
|
||||
INSTANTIATE(multiset)<test::minimal::assignable,
|
||||
test::minimal::hash<test::minimal::assignable>,
|
||||
test::minimal::equal_to<test::minimal::assignable>,
|
||||
test::minimal::allocator<int> >;
|
||||
|
||||
@@ -50,6 +50,8 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::reference reference;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::const_reference const_reference;
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
|
||||
// value_type
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, value_type>::value));
|
||||
@@ -72,6 +74,9 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
boost::function_requires<boost::InputIteratorConcept<const_iterator> >();
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, const_iterator_value_type>::value));
|
||||
|
||||
// node_type
|
||||
// TODO?
|
||||
|
||||
// difference_type
|
||||
|
||||
BOOST_STATIC_ASSERT(std::numeric_limits<difference_type>::is_signed);
|
||||
@@ -140,6 +145,24 @@ template <class X, class T> void container_test(X& r, T const&)
|
||||
sink(X(rvalue(a_const), m));
|
||||
X c3(rvalue(a_const), m);
|
||||
|
||||
// node_type
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
BOOST_STATIC_ASSERT(boost::is_same<allocator_type,
|
||||
BOOST_DEDUCED_TYPENAME node_type::allocator_type>::value);
|
||||
|
||||
node_type n1;
|
||||
node_type n2(rvalue_default<node_type>());
|
||||
node_type n3;
|
||||
n3 = boost::move(n2);
|
||||
n1.swap(n3);
|
||||
swap(n1, n3);
|
||||
|
||||
node_type const n_const;
|
||||
BOOST_TEST(n_const ? 0 : 1);
|
||||
test::check_return_type<bool>::equals(!n_const);
|
||||
test::check_return_type<bool>::equals(n_const.empty());
|
||||
|
||||
// Avoid unused variable warnings:
|
||||
|
||||
sink(u);
|
||||
@@ -197,7 +220,7 @@ template <class X> void unordered_destructible_test(X&)
|
||||
test::check_return_type<allocator_type>::equals(a_const.get_allocator());
|
||||
}
|
||||
|
||||
template <class X, class Key> void unordered_set_test(X&, Key const&)
|
||||
template <class X, class Key> void unordered_set_test(X& r, Key const&)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME X::value_type value_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::key_type key_type;
|
||||
@@ -227,6 +250,18 @@ template <class X, class Key> void unordered_set_test(X&, Key const&)
|
||||
(boost::is_same<value_type const*, local_iterator_pointer>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*,
|
||||
const_local_iterator_pointer>::value));
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_type::value_type node_value_type;
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type, node_value_type>::value));
|
||||
|
||||
// Call node_type functions.
|
||||
|
||||
test::minimal::constructor_param v;
|
||||
Key k_lvalue(v);
|
||||
r.emplace(boost::move(k_lvalue));
|
||||
node_type n1 = r.extract(r.begin());
|
||||
test::check_return_type<value_type>::equals_ref(n1.value());
|
||||
}
|
||||
|
||||
template <class X, class Key, class T>
|
||||
@@ -261,6 +296,13 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
BOOST_STATIC_ASSERT((boost::is_same<value_type const*,
|
||||
const_local_iterator_pointer>::value));
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_type::key_type node_key_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME node_type::mapped_type node_mapped_type;
|
||||
|
||||
BOOST_STATIC_ASSERT((boost::is_same<Key, node_key_type>::value));
|
||||
BOOST_STATIC_ASSERT((boost::is_same<T, node_mapped_type>::value));
|
||||
|
||||
// Calling functions
|
||||
|
||||
r.insert(std::pair<Key const, T>(k, v));
|
||||
@@ -274,6 +316,19 @@ void unordered_map_test(X& r, Key const& k, T const& v)
|
||||
|
||||
r.emplace(boost::unordered::piecewise_construct, boost::make_tuple(k),
|
||||
boost::make_tuple(v));
|
||||
|
||||
test::check_return_type<node_type>::equals(r.extract(r.begin()));
|
||||
|
||||
r.emplace(k, v);
|
||||
test::check_return_type<node_type>::equals(r.extract(k));
|
||||
|
||||
r.emplace(k, v);
|
||||
node_type n1 = r.extract(r.begin());
|
||||
test::check_return_type<key_type>::equals_ref(n1.key());
|
||||
test::check_return_type<T>::equals_ref(n1.mapped());
|
||||
|
||||
r.insert(boost::move(n1));
|
||||
r.insert(r.end(), r.extract(r.begin()));
|
||||
}
|
||||
|
||||
template <class X> void equality_test(X& r)
|
||||
@@ -291,6 +346,28 @@ template <class X, class T> void unordered_unique_test(X& r, T const& t)
|
||||
typedef BOOST_DEDUCED_TYPENAME X::iterator iterator;
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(r.insert(t));
|
||||
test::check_return_type<std::pair<iterator, bool> >::equals(r.emplace(t));
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::insert_return_type insert_return_type;
|
||||
|
||||
// insert_return_type
|
||||
|
||||
// TODO;
|
||||
// boost::function_requires<boost::MoveConstructibleConcept<insert_return_type>
|
||||
// >();
|
||||
// TODO;
|
||||
// boost::function_requires<boost::MoveAssignableConcept<insert_return_type>
|
||||
// >();
|
||||
boost::function_requires<
|
||||
boost::DefaultConstructibleConcept<insert_return_type> >();
|
||||
// TODO:
|
||||
// boost::function_requires<boost::DestructibleConcept<insert_return_type>
|
||||
// >();
|
||||
insert_return_type insert_return, insert_return2;
|
||||
test::check_return_type<bool>::equals(insert_return.inserted);
|
||||
test::check_return_type<iterator>::equals(insert_return.position);
|
||||
test::check_return_type<node_type>::equals_ref(insert_return.node);
|
||||
boost::swap(insert_return, insert_return2);
|
||||
}
|
||||
|
||||
template <class X, class T> void unordered_equivalent_test(X& r, T const& t)
|
||||
@@ -580,6 +657,11 @@ void unordered_copyable_test(X& x, Key& k, T& t, Hash& hf, Pred& eq)
|
||||
sink(a6a);
|
||||
sink(a7a);
|
||||
sink(a9a);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME X::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME X::allocator_type allocator_type;
|
||||
node_type const n_const = a.extract(a.begin());
|
||||
test::check_return_type<allocator_type>::equals(n_const.get_allocator());
|
||||
}
|
||||
|
||||
template <class X, class Key, class T, class Hash, class Pred>
|
||||
|
||||
140
test/unordered/extract_tests.cpp
Normal file
140
test/unordered/extract_tests.cpp
Normal file
@@ -0,0 +1,140 @@
|
||||
|
||||
// Copyright 2016 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
// clang-format off
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include "../helpers/postfix.hpp"
|
||||
// clang-format on
|
||||
|
||||
#include "../helpers/equivalent.hpp"
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include "../helpers/invariants.hpp"
|
||||
#include "../helpers/random_values.hpp"
|
||||
#include "../helpers/test.hpp"
|
||||
#include "../helpers/tracker.hpp"
|
||||
#include "../objects/test.hpp"
|
||||
#include <boost/next_prior.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace extract_tests {
|
||||
|
||||
test::seed_t initialize_seed(85638);
|
||||
|
||||
template <class Container>
|
||||
void extract_tests1(Container*, test::random_generator generator)
|
||||
{
|
||||
std::cerr << "Extract by key.\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
int iterations = 0;
|
||||
for (BOOST_DEDUCED_TYPENAME test::random_values<Container>::iterator
|
||||
it = v.begin();
|
||||
it != v.end(); ++it) {
|
||||
std::size_t count = x.count(test::get_key<Container>(*it));
|
||||
std::size_t old_size = x.size();
|
||||
std::size_t new_count = count ? count - 1 : count;
|
||||
std::size_t new_size = count ? old_size - 1 : old_size;
|
||||
typename Container::node_type n =
|
||||
x.extract(test::get_key<Container>(*it));
|
||||
BOOST_TEST((bool)n == (bool)count);
|
||||
BOOST_TEST(x.size() == new_size);
|
||||
BOOST_TEST(x.count(test::get_key<Container>(*it)) == new_count);
|
||||
if (!new_count) {
|
||||
BOOST_TEST(x.find(test::get_key<Container>(*it)) == x.end());
|
||||
} else {
|
||||
BOOST_TEST(x.find(test::get_key<Container>(*it)) != x.end());
|
||||
}
|
||||
if (++iterations % 20 == 0)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "extract(begin()).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while (size > 0 && !x.empty()) {
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type key =
|
||||
test::get_key<Container>(*x.begin());
|
||||
std::size_t count = x.count(key);
|
||||
typename Container::node_type n = x.extract(x.begin());
|
||||
BOOST_TEST(n);
|
||||
--size;
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "extract(random position).\n";
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
||||
test::random_values<Container> v(1000, generator);
|
||||
Container x(v.begin(), v.end());
|
||||
std::size_t size = x.size();
|
||||
int iterations = 0;
|
||||
while (size > 0 && !x.empty()) {
|
||||
using namespace std;
|
||||
int index = rand() % (int)x.size();
|
||||
BOOST_DEDUCED_TYPENAME Container::const_iterator prev, pos, next;
|
||||
if (index == 0) {
|
||||
prev = pos = x.begin();
|
||||
} else {
|
||||
prev = boost::next(x.begin(), index - 1);
|
||||
pos = boost::next(prev);
|
||||
}
|
||||
next = boost::next(pos);
|
||||
BOOST_DEDUCED_TYPENAME Container::key_type key =
|
||||
test::get_key<Container>(*pos);
|
||||
std::size_t count = x.count(key);
|
||||
typename Container::node_type n = x.extract(pos);
|
||||
BOOST_TEST(n);
|
||||
--size;
|
||||
if (size > 0)
|
||||
BOOST_TEST(
|
||||
index == 0 ? next == x.begin() : next == boost::next(prev));
|
||||
BOOST_TEST(x.count(key) == count - 1);
|
||||
BOOST_TEST(x.size() == size);
|
||||
if (++iterations % 20 == 0)
|
||||
test::check_equivalent_keys(x);
|
||||
}
|
||||
BOOST_TEST(x.empty());
|
||||
}
|
||||
|
||||
std::cerr << "\n";
|
||||
}
|
||||
|
||||
boost::unordered_set<test::object, test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_set;
|
||||
boost::unordered_multiset<test::object, test::hash, test::equal_to,
|
||||
test::allocator2<test::object> >* test_multiset;
|
||||
boost::unordered_map<test::object, test::object, test::hash, test::equal_to,
|
||||
test::allocator1<test::object> >* test_map;
|
||||
boost::unordered_multimap<test::object, test::object, test::hash,
|
||||
test::equal_to, test::allocator2<test::object> >* test_multimap;
|
||||
|
||||
using test::default_generator;
|
||||
using test::generate_collisions;
|
||||
|
||||
UNORDERED_TEST(
|
||||
extract_tests1, ((test_set)(test_multiset)(test_map)(test_multimap))(
|
||||
(default_generator)(generate_collisions)))
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
29
test/unordered/insert_node_type_fail.cpp
Normal file
29
test/unordered/insert_node_type_fail.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
int main()
|
||||
{
|
||||
#if defined(UNORDERED_TEST_MAP)
|
||||
typedef boost::unordered_map<int, int> container;
|
||||
container x;
|
||||
x.emplace(1, 1);
|
||||
#elif defined(UNORDERED_TEST_MULTIMAP)
|
||||
typedef boost::unordered_multimap<int, int> container;
|
||||
container x;
|
||||
#elif defined(UNORDERED_TEST_SET)
|
||||
typedef boost::unordered_set<int> container;
|
||||
container x;
|
||||
x.emplace(1);
|
||||
#elif defined(UNORDERED_TEST_MULTISET)
|
||||
typedef boost::unordered_multiset<int> container;
|
||||
container x;
|
||||
x.emplace(1);
|
||||
#else
|
||||
#define UNORDERED_ERROR
|
||||
#endif
|
||||
|
||||
#if !defined(UNORDERED_ERROR)
|
||||
container::node_type n = x.extract(x.begin());
|
||||
x.insert(n);
|
||||
#endif
|
||||
}
|
||||
436
test/unordered/node_handle_tests.cpp
Normal file
436
test/unordered/node_handle_tests.cpp
Normal file
@@ -0,0 +1,436 @@
|
||||
|
||||
// Copyright 2016 Daniel James.
|
||||
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||||
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
#include "../helpers/postfix.hpp"
|
||||
#include "../helpers/prefix.hpp"
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/unordered_set.hpp>
|
||||
|
||||
#include "../helpers/helpers.hpp"
|
||||
#include "../helpers/metafunctions.hpp"
|
||||
#include "../helpers/test.hpp"
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
UNORDERED_AUTO_TEST(example1)
|
||||
{
|
||||
typedef boost::unordered_map<int, std::string>::insert_return_type
|
||||
insert_return_type;
|
||||
|
||||
boost::unordered_map<int, std::string> src;
|
||||
src.emplace(1, "one");
|
||||
src.emplace(2, "two");
|
||||
src.emplace(3, "buckle my shoe");
|
||||
boost::unordered_map<int, std::string> dst;
|
||||
dst.emplace(3, "three");
|
||||
|
||||
dst.insert(src.extract(src.find(1)));
|
||||
dst.insert(src.extract(2));
|
||||
insert_return_type r = dst.insert(src.extract(3));
|
||||
|
||||
BOOST_TEST(src.empty());
|
||||
BOOST_TEST(dst.size() == 3);
|
||||
BOOST_TEST(dst[1] == "one");
|
||||
BOOST_TEST(dst[2] == "two");
|
||||
BOOST_TEST(dst[3] == "three");
|
||||
BOOST_TEST(!r.inserted);
|
||||
BOOST_TEST(r.position == dst.find(3));
|
||||
BOOST_TEST(r.node.mapped() == "buckle my shoe");
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(example2)
|
||||
{
|
||||
boost::unordered_set<int> src;
|
||||
src.insert(1);
|
||||
src.insert(3);
|
||||
src.insert(5);
|
||||
boost::unordered_set<int> dst;
|
||||
dst.insert(2);
|
||||
dst.insert(4);
|
||||
dst.insert(5);
|
||||
// dst.merge(src);
|
||||
// Merge src into dst.
|
||||
// src == {5}
|
||||
// dst == {1, 2, 3, 4, 5}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(example3)
|
||||
{
|
||||
typedef boost::unordered_set<int>::iterator iterator;
|
||||
|
||||
boost::unordered_set<int> src;
|
||||
src.insert(1);
|
||||
src.insert(3);
|
||||
src.insert(5);
|
||||
boost::unordered_set<int> dst;
|
||||
dst.insert(2);
|
||||
dst.insert(4);
|
||||
dst.insert(5);
|
||||
for (iterator i = src.begin(); i != src.end();) {
|
||||
std::pair<iterator, iterator> p = dst.equal_range(*i);
|
||||
if (p.first == p.second)
|
||||
dst.insert(p.first, src.extract(i++));
|
||||
else
|
||||
++i;
|
||||
}
|
||||
BOOST_TEST(src.size() == 1);
|
||||
BOOST_TEST(*src.begin() == 5);
|
||||
|
||||
std::set<int> dst2(dst.begin(), dst.end());
|
||||
std::set<int>::iterator it = dst2.begin();
|
||||
BOOST_TEST(*it++ == 1);
|
||||
BOOST_TEST(*it++ == 2);
|
||||
BOOST_TEST(*it++ == 3);
|
||||
BOOST_TEST(*it++ == 4);
|
||||
BOOST_TEST(*it++ == 5);
|
||||
BOOST_TEST(it == dst2.end());
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(failed_insertion_with_hint)
|
||||
{
|
||||
{
|
||||
boost::unordered_set<int> src;
|
||||
boost::unordered_set<int> dst;
|
||||
src.emplace(10);
|
||||
src.emplace(20);
|
||||
dst.emplace(10);
|
||||
dst.emplace(20);
|
||||
|
||||
boost::unordered_set<int>::node_type nh = src.extract(10);
|
||||
|
||||
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
|
||||
BOOST_TEST(nh);
|
||||
BOOST_TEST(!nh.empty());
|
||||
BOOST_TEST(nh.value() == 10);
|
||||
|
||||
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
|
||||
BOOST_TEST(nh);
|
||||
BOOST_TEST(!nh.empty());
|
||||
BOOST_TEST(nh.value() == 10);
|
||||
|
||||
BOOST_TEST(src.count(10) == 0);
|
||||
BOOST_TEST(src.count(20) == 1);
|
||||
BOOST_TEST(dst.count(10) == 1);
|
||||
BOOST_TEST(dst.count(20) == 1);
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_map<int, int> src;
|
||||
boost::unordered_map<int, int> dst;
|
||||
src.emplace(10, 30);
|
||||
src.emplace(20, 5);
|
||||
dst.emplace(10, 20);
|
||||
dst.emplace(20, 2);
|
||||
|
||||
boost::unordered_map<int, int>::node_type nh = src.extract(10);
|
||||
BOOST_TEST(dst.insert(dst.find(10), boost::move(nh)) == dst.find(10));
|
||||
BOOST_TEST(nh);
|
||||
BOOST_TEST(!nh.empty());
|
||||
BOOST_TEST(nh.key() == 10);
|
||||
BOOST_TEST(nh.mapped() == 30);
|
||||
BOOST_TEST(dst[10] == 20);
|
||||
|
||||
BOOST_TEST(dst.insert(dst.find(20), boost::move(nh)) == dst.find(10));
|
||||
BOOST_TEST(nh);
|
||||
BOOST_TEST(!nh.empty());
|
||||
BOOST_TEST(nh.key() == 10);
|
||||
BOOST_TEST(nh.mapped() == 30);
|
||||
BOOST_TEST(dst[10] == 20);
|
||||
|
||||
BOOST_TEST(src.count(10) == 0);
|
||||
BOOST_TEST(src.count(20) == 1);
|
||||
BOOST_TEST(dst.count(10) == 1);
|
||||
BOOST_TEST(dst.count(20) == 1);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename NodeHandle>
|
||||
bool node_handle_compare(NodeHandle const& nh,
|
||||
BOOST_DEDUCED_TYPENAME NodeHandle::value_type const& x)
|
||||
{
|
||||
return x == nh.value();
|
||||
}
|
||||
|
||||
template <typename NodeHandle>
|
||||
bool node_handle_compare(
|
||||
NodeHandle const& nh,
|
||||
std::pair<BOOST_DEDUCED_TYPENAME NodeHandle::key_type const,
|
||||
BOOST_DEDUCED_TYPENAME NodeHandle::mapped_type> const& x)
|
||||
{
|
||||
return x.first == nh.key() && x.second == nh.mapped();
|
||||
}
|
||||
|
||||
template <typename Container> void node_handle_tests_impl(Container& c)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container::node_type node_type;
|
||||
|
||||
BOOST_DEDUCED_TYPENAME Container::value_type value = *c.begin();
|
||||
|
||||
node_type n1;
|
||||
BOOST_TEST(!n1);
|
||||
BOOST_TEST(n1.empty());
|
||||
|
||||
node_type n2 = c.extract(c.begin());
|
||||
BOOST_TEST(n2);
|
||||
BOOST_TEST(!n2.empty());
|
||||
node_handle_compare(n2, value);
|
||||
|
||||
node_type n3 = boost::move(n2);
|
||||
BOOST_TEST(n3);
|
||||
BOOST_TEST(!n2);
|
||||
node_handle_compare(n3, value);
|
||||
// TODO: Check that n2 doesn't have an allocator?
|
||||
// Maybe by swapping and observing that the allocator is
|
||||
// swapped rather than moved?
|
||||
|
||||
n1 = boost::move(n3);
|
||||
BOOST_TEST(n1);
|
||||
BOOST_TEST(!n3);
|
||||
node_handle_compare(n1, value);
|
||||
|
||||
// Self move-assignment empties the node_handle.
|
||||
n1 = boost::move(n1);
|
||||
BOOST_TEST(!n1);
|
||||
|
||||
n3 = boost::move(n3);
|
||||
BOOST_TEST(!n3);
|
||||
|
||||
BOOST_DEDUCED_TYPENAME Container::value_type value1 = *c.begin();
|
||||
n1 = c.extract(c.begin());
|
||||
BOOST_DEDUCED_TYPENAME Container::value_type value2 = *c.begin();
|
||||
n2 = c.extract(c.begin());
|
||||
n3 = node_type();
|
||||
|
||||
node_handle_compare(n1, value1);
|
||||
node_handle_compare(n2, value2);
|
||||
n1.swap(n2);
|
||||
BOOST_TEST(n1);
|
||||
BOOST_TEST(n2);
|
||||
node_handle_compare(n1, value2);
|
||||
node_handle_compare(n2, value1);
|
||||
|
||||
BOOST_TEST(n1);
|
||||
BOOST_TEST(!n3);
|
||||
n1.swap(n3);
|
||||
BOOST_TEST(!n1);
|
||||
BOOST_TEST(n3);
|
||||
node_handle_compare(n3, value2);
|
||||
|
||||
BOOST_TEST(!n1);
|
||||
BOOST_TEST(n2);
|
||||
n1.swap(n2);
|
||||
BOOST_TEST(n1);
|
||||
BOOST_TEST(!n2);
|
||||
node_handle_compare(n1, value1);
|
||||
|
||||
node_type n4;
|
||||
BOOST_TEST(!n2);
|
||||
BOOST_TEST(!n4);
|
||||
n2.swap(n4);
|
||||
BOOST_TEST(!n2);
|
||||
BOOST_TEST(!n4);
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(node_handle_tests)
|
||||
{
|
||||
boost::unordered_set<int> x1;
|
||||
x1.emplace(100);
|
||||
x1.emplace(140);
|
||||
x1.emplace(-55);
|
||||
node_handle_tests_impl(x1);
|
||||
|
||||
boost::unordered_map<int, std::string> x2;
|
||||
x2.emplace(10, "ten");
|
||||
x2.emplace(-23, "twenty");
|
||||
x2.emplace(-76, "thirty");
|
||||
node_handle_tests_impl(x2);
|
||||
}
|
||||
|
||||
template <typename Container1, typename Container2>
|
||||
void insert_node_handle_unique(Container1& c1, Container2& c2)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
|
||||
BOOST_STATIC_ASSERT(boost::is_same<node_type,
|
||||
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
|
||||
insert_return_type1;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
|
||||
insert_return_type2;
|
||||
|
||||
insert_return_type1 r1 = c1.insert(node_type());
|
||||
insert_return_type2 r2 = c2.insert(node_type());
|
||||
BOOST_TEST(!r1.inserted);
|
||||
BOOST_TEST(!r1.node);
|
||||
BOOST_TEST(r1.position == c1.end());
|
||||
BOOST_TEST(!r2.inserted);
|
||||
BOOST_TEST(!r2.node);
|
||||
BOOST_TEST(r2.position == c2.end());
|
||||
|
||||
while (!c1.empty()) {
|
||||
value_type v = *c1.begin();
|
||||
value_type const* v_ptr = boost::addressof(*c1.begin());
|
||||
std::size_t count = c2.count(test::get_key<Container1>(v));
|
||||
insert_return_type2 r = c2.insert(c1.extract(c1.begin()));
|
||||
if (!count) {
|
||||
BOOST_TEST(r.inserted);
|
||||
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
|
||||
BOOST_TEST(r.position != c2.end());
|
||||
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
|
||||
BOOST_TEST(!r.node);
|
||||
} else {
|
||||
BOOST_TEST(!r.inserted);
|
||||
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
|
||||
BOOST_TEST(r.position != c2.end());
|
||||
BOOST_TEST(test::get_key<Container2>(*r.position) ==
|
||||
test::get_key<Container2>(v));
|
||||
BOOST_TEST(r.node);
|
||||
node_handle_compare(r.node, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container1, typename Container2>
|
||||
void insert_node_handle_unique2(Container1& c1, Container2& c2)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
|
||||
BOOST_STATIC_ASSERT(boost::is_same<node_type,
|
||||
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
|
||||
|
||||
// typedef BOOST_DEDUCED_TYPENAME Container1::insert_return_type
|
||||
// insert_return_type1;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container2::insert_return_type
|
||||
insert_return_type2;
|
||||
|
||||
while (!c1.empty()) {
|
||||
value_type v = *c1.begin();
|
||||
value_type const* v_ptr = boost::addressof(*c1.begin());
|
||||
std::size_t count = c2.count(test::get_key<Container1>(v));
|
||||
insert_return_type2 r =
|
||||
c2.insert(c1.extract(test::get_key<Container1>(v)));
|
||||
if (r.inserted) {
|
||||
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
|
||||
BOOST_TEST(r.position != c2.end());
|
||||
BOOST_TEST(boost::addressof(*r.position) == v_ptr);
|
||||
BOOST_TEST(!r.node);
|
||||
} else {
|
||||
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count);
|
||||
BOOST_TEST(r.position != c2.end());
|
||||
BOOST_TEST(test::get_key<Container2>(*r.position) ==
|
||||
test::get_key<Container2>(v));
|
||||
BOOST_TEST(r.node);
|
||||
node_handle_compare(r.node, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container1, typename Container2>
|
||||
void insert_node_handle_equiv(Container1& c1, Container2& c2)
|
||||
{
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::node_type node_type;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::value_type value_type;
|
||||
BOOST_STATIC_ASSERT(boost::is_same<node_type,
|
||||
BOOST_DEDUCED_TYPENAME Container2::node_type>::value);
|
||||
|
||||
typedef BOOST_DEDUCED_TYPENAME Container1::iterator iterator1;
|
||||
typedef BOOST_DEDUCED_TYPENAME Container2::iterator iterator2;
|
||||
|
||||
iterator1 r1 = c1.insert(node_type());
|
||||
iterator2 r2 = c2.insert(node_type());
|
||||
BOOST_TEST(r1 == c1.end());
|
||||
BOOST_TEST(r2 == c2.end());
|
||||
|
||||
while (!c1.empty()) {
|
||||
value_type v = *c1.begin();
|
||||
value_type const* v_ptr = boost::addressof(*c1.begin());
|
||||
std::size_t count = c2.count(test::get_key<Container1>(v));
|
||||
iterator2 r = c2.insert(c1.extract(c1.begin()));
|
||||
BOOST_TEST_EQ(c2.count(test::get_key<Container1>(v)), count + 1);
|
||||
BOOST_TEST(r != c2.end());
|
||||
BOOST_TEST(boost::addressof(*r) == v_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
struct hash_thing
|
||||
{
|
||||
std::size_t operator()(int x) const
|
||||
{
|
||||
return static_cast<std::size_t>(x * 13 + 5);
|
||||
}
|
||||
};
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests)
|
||||
{
|
||||
{
|
||||
boost::unordered_set<int> x1;
|
||||
boost::unordered_set<int> x2;
|
||||
x1.emplace(100);
|
||||
x1.emplace(140);
|
||||
x1.emplace(-55);
|
||||
x2.emplace(140);
|
||||
insert_node_handle_unique(x1, x2);
|
||||
BOOST_TEST(x2.size() == 3);
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_map<int, int, hash_thing> x1;
|
||||
boost::unordered_map<int, int> x2;
|
||||
x1.emplace(67, 50);
|
||||
x1.emplace(23, 45);
|
||||
x1.emplace(18, 19);
|
||||
x2.emplace(23, 50);
|
||||
x2.emplace(12, 49);
|
||||
insert_node_handle_unique(x1, x2);
|
||||
BOOST_TEST(x2.size() == 4);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_node_handle_equiv_tests)
|
||||
{
|
||||
{
|
||||
boost::unordered_multimap<int, int, hash_thing> x1;
|
||||
boost::unordered_multimap<int, int> x2;
|
||||
x1.emplace(67, 50);
|
||||
x1.emplace(67, 100);
|
||||
x1.emplace(23, 45);
|
||||
x1.emplace(18, 19);
|
||||
x2.emplace(23, 50);
|
||||
x2.emplace(12, 49);
|
||||
insert_node_handle_equiv(x1, x2);
|
||||
BOOST_TEST(x2.size() == 6);
|
||||
}
|
||||
}
|
||||
|
||||
UNORDERED_AUTO_TEST(insert_node_handle_unique_tests2)
|
||||
{
|
||||
{
|
||||
boost::unordered_set<int> x1;
|
||||
boost::unordered_set<int> x2;
|
||||
x1.emplace(100);
|
||||
x1.emplace(140);
|
||||
x1.emplace(-55);
|
||||
x2.emplace(140);
|
||||
insert_node_handle_unique2(x1, x2);
|
||||
BOOST_TEST(x2.size() == 3);
|
||||
}
|
||||
|
||||
{
|
||||
boost::unordered_map<int, int, hash_thing> x1;
|
||||
boost::unordered_map<int, int> x2;
|
||||
x1.emplace(67, 50);
|
||||
x1.emplace(23, 45);
|
||||
x1.emplace(18, 19);
|
||||
x2.emplace(23, 50);
|
||||
x2.emplace(12, 49);
|
||||
insert_node_handle_unique2(x1, x2);
|
||||
BOOST_TEST(x2.size() == 4);
|
||||
}
|
||||
}
|
||||
|
||||
RUN_TESTS()
|
||||
Reference in New Issue
Block a user