forked from boostorg/unordered
Merge between set/multiset and map/multimap
This commit is contained in:
@ -34,6 +34,8 @@
|
||||
#include <boost/type_traits/is_empty.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_assignable.hpp>
|
||||
#include <boost/type_traits/is_nothrow_move_constructible.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <boost/type_traits/remove_const.hpp>
|
||||
#include <boost/unordered/detail/fwd.hpp>
|
||||
#include <boost/utility/addressof.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
@ -730,11 +732,8 @@ template <typename T> struct identity
|
||||
#if BOOST_UNORDERED_USE_ALLOCATOR_TRAITS == 0
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include <boost/pointer_to_other.hpp>
|
||||
#if defined(BOOST_NO_SFINAE_EXPR)
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#endif
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \
|
||||
!defined(BOOST_NO_SFINAE_EXPR)
|
||||
@ -3609,6 +3608,7 @@ struct table_impl : boost::unordered::detail::table<Types>
|
||||
{
|
||||
typedef boost::unordered::detail::table<Types> table;
|
||||
typedef typename table::value_type value_type;
|
||||
typedef typename table::node node;
|
||||
typedef typename table::bucket bucket;
|
||||
typedef typename table::policy policy;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
@ -4001,13 +4001,19 @@ struct table_impl : boost::unordered::detail::table<Types>
|
||||
return iterator(pos);
|
||||
}
|
||||
|
||||
template <typename Types2> void merge_impl(table_impl<Types2>& other)
|
||||
template <typename Types2>
|
||||
void merge_impl(boost::unordered::detail::table<Types2>& other)
|
||||
{
|
||||
typedef boost::unordered::detail::table<Types2> other_table;
|
||||
BOOST_STATIC_ASSERT(
|
||||
(boost::is_same<node, typename other_table::node>::value));
|
||||
BOOST_ASSERT(this->node_alloc() == other.node_alloc());
|
||||
|
||||
if (other.size_) {
|
||||
link_pointer prev = other.get_previous_start();
|
||||
|
||||
while (prev->next_) {
|
||||
node_pointer n = Types2::node_algo::next_node(prev);
|
||||
node_pointer n = other_table::node_algo::next_node(prev);
|
||||
const_key_type& k = this->get_key(n->value());
|
||||
std::size_t key_hash = this->hash(k);
|
||||
node_pointer pos = this->find_node(key_hash, k);
|
||||
@ -4016,6 +4022,8 @@ struct table_impl : boost::unordered::detail::table<Types>
|
||||
prev = n;
|
||||
} else {
|
||||
this->reserve_for_insert(this->size_ + 1);
|
||||
other_table::node_algo::split_groups(
|
||||
n, other_table::node_algo::next_node(n));
|
||||
prev->next_ = n->next_;
|
||||
--other.size_;
|
||||
other.fix_bucket(other.hash_to_bucket(n->hash_), prev);
|
||||
|
@ -39,6 +39,8 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_map)
|
||||
#endif
|
||||
template <typename, typename, typename, typename, typename>
|
||||
friend class unordered_multimap;
|
||||
|
||||
public:
|
||||
typedef K key_type;
|
||||
@ -619,14 +621,21 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_map<K, T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_multimap<K,T,H2,P2,A>& source);
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_multimap<K,T,H2,P2,A>&& source);
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
@ -723,6 +732,9 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_multimap)
|
||||
#endif
|
||||
template <typename, typename, typename, typename, typename>
|
||||
friend class unordered_map;
|
||||
|
||||
public:
|
||||
typedef K key_type;
|
||||
typedef std::pair<const K, T> value_type;
|
||||
@ -1068,14 +1080,21 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multimap<K, T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_map<K,T,H2,P2,A>& source);
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_map<K,T,H2,P2,A>&& source);
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_map<K, T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
@ -1396,6 +1415,26 @@ void unordered_map<K, T, H, P, A>::merge(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_map<K, T, H, P, A>::merge(
|
||||
boost::unordered_multimap<K, T, H2, P2, A>& source)
|
||||
{
|
||||
table_.merge_impl(source.table_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_map<K, T, H, P, A>::merge(
|
||||
boost::unordered_multimap<K, T, H2, P2, A>&& source)
|
||||
{
|
||||
table_.merge_impl(source.table_);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@ -1818,6 +1857,30 @@ void unordered_multimap<K, T, H, P, A>::merge(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_multimap<K, T, H, P, A>::merge(
|
||||
boost::unordered_map<K, T, H2, P2, A>& source)
|
||||
{
|
||||
while (!source.empty()) {
|
||||
insert(source.extract(source.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class K, class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_multimap<K, T, H, P, A>::merge(
|
||||
boost::unordered_map<K, T, H2, P2, A>&& source)
|
||||
{
|
||||
while (!source.empty()) {
|
||||
insert(source.extract(source.begin()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
|
@ -39,6 +39,9 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_set)
|
||||
#endif
|
||||
template <typename, typename, typename, typename>
|
||||
friend class unordered_multiset;
|
||||
|
||||
public:
|
||||
typedef T key_type;
|
||||
typedef T value_type;
|
||||
@ -393,14 +396,21 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_set<T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_set<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_multiset<T,H2,P2,A>& source);
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_multiset<T,H2,P2,A>&& source);
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multiset<T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
@ -486,6 +496,9 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
BOOST_COPYABLE_AND_MOVABLE(unordered_multiset)
|
||||
#endif
|
||||
template <typename, typename, typename, typename>
|
||||
friend class unordered_set;
|
||||
|
||||
public:
|
||||
typedef T key_type;
|
||||
typedef T value_type;
|
||||
@ -830,14 +843,21 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multiset<T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_set<T,H2,P2,A>& source);
|
||||
// template <typename H2, typename P2>
|
||||
// void merge(boost::unordered_set<T,H2,P2,A>&& source);
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_set<T, H2, P2, A>& source);
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <typename H2, typename P2>
|
||||
void merge(boost::unordered_set<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
@ -1163,6 +1183,26 @@ void unordered_set<T, H, P, A>::merge(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_set<T, H, P, A>::merge(
|
||||
boost::unordered_multiset<T, H2, P2, A>& source)
|
||||
{
|
||||
table_.merge_impl(source.table_);
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_set<T, H, P, A>::merge(
|
||||
boost::unordered_multiset<T, H2, P2, A>&& source)
|
||||
{
|
||||
table_.merge_impl(source.table_);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@ -1522,6 +1562,30 @@ void unordered_multiset<T, H, P, A>::merge(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
template <class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_multiset<T, H, P, A>::merge(
|
||||
boost::unordered_set<T, H2, P2, A>& source)
|
||||
{
|
||||
while (!source.empty()) {
|
||||
insert(source.extract(source.begin()));
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
|
||||
template <class T, class H, class P, class A>
|
||||
template <typename H2, typename P2>
|
||||
void unordered_multiset<T, H, P, A>::merge(
|
||||
boost::unordered_set<T, H2, P2, A>&& source)
|
||||
{
|
||||
while (!source.empty()) {
|
||||
insert(source.extract(source.begin()));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
|
@ -99,6 +99,48 @@ UNORDERED_AUTO_TEST(merge_multiset)
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
UNORDERED_AUTO_TEST(merge_set_and_multiset)
|
||||
{
|
||||
boost::unordered_set<int> x;
|
||||
boost::unordered_multiset<int> y;
|
||||
|
||||
x.merge(y);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(y.empty());
|
||||
|
||||
x.insert(10);
|
||||
x.merge(y);
|
||||
BOOST_TEST(x.size() == 1);
|
||||
BOOST_TEST(x.count(10) == 1);
|
||||
BOOST_TEST(y.empty());
|
||||
|
||||
y.merge(x);
|
||||
BOOST_TEST(x.empty());
|
||||
BOOST_TEST(y.size() == 1);
|
||||
BOOST_TEST(y.count(10) == 1);
|
||||
|
||||
x.insert(10);
|
||||
x.insert(50);
|
||||
y.insert(70);
|
||||
y.insert(80);
|
||||
x.merge(y);
|
||||
BOOST_TEST_EQ(x.size(), 4u);
|
||||
BOOST_TEST_EQ(y.size(), 1u);
|
||||
BOOST_TEST_EQ(x.count(10), 1u);
|
||||
BOOST_TEST_EQ(x.count(50), 1u);
|
||||
BOOST_TEST_EQ(x.count(70), 1u);
|
||||
BOOST_TEST_EQ(x.count(80), 1u);
|
||||
BOOST_TEST_EQ(y.count(10), 1u);
|
||||
BOOST_TEST_EQ(y.count(50), 0u);
|
||||
BOOST_TEST_EQ(y.count(70), 0u);
|
||||
BOOST_TEST_EQ(y.count(80), 0u);
|
||||
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X> void merge_empty_test(X*, test::random_generator generator)
|
||||
{
|
||||
test::check_instances check_;
|
||||
|
Reference in New Issue
Block a user