mirror of
https://github.com/boostorg/unordered.git
synced 2025-07-31 20:04:29 +02:00
Merge branch 'feature/simpler-data-structure' into develop
C++17 requires that unordered_map has the same type of node as unordered_multimap, and that unordered_set has the same type of node as unordered_multiset. This didn't seem particularly useful to me and contradicts the old implementation which had different nodes, I put a lot of effort into trying to abstract out the difference and make it selectable using a macro, so that the old implementation would still by available for anyone who doesn't care about strict compatibility. But I think that was a mistake, it was making things too complicated and for too little gain. The default would still be inefficient containers for equivalent keys, and using the macro could lead to problems down the line. So I've switched to using a much simpler implementation which just marks the first node in a group of equivalent nodes. This isn't as fast when there are a lot of elements with equivalent keys - it can't skip to the end of a group of nodes, but at least it avoids having to do a lot of potentially expensive comparisons. It's also a lot closer to the intent of the standard, even if I disagree with that intent.
This commit is contained in:
@@ -38,14 +38,6 @@ matrix:
|
||||
env: |
|
||||
label="clang 32 bit";
|
||||
user_config="using clang : : clang++ -m32 -Werror --std=c++03 ;"
|
||||
- compiler: gcc
|
||||
env: |
|
||||
label="gcc C++03 interopable1";
|
||||
user_config="using gcc : : g++-4.8 -fsanitize=address -Werror --std=c++03 -DBOOST_UNORDERED_INTEROPERABLE_NODES=1 ;"
|
||||
- compiler: clang
|
||||
env: |
|
||||
label="gcc C++11 interopable2";
|
||||
user_config="using clang : : clang++ -fsanitize=address -Werror --std=c++03 -DBOOST_UNORDERED_INTEROPERABLE_NODES=2 ;"
|
||||
|
||||
before_script:
|
||||
- cd ${TRAVIS_BUILD_DIR}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -23,22 +23,13 @@ template <typename A, typename K, typename M, typename H, typename P> struct map
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES != 2
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<value_type> extractor;
|
||||
enum
|
||||
{
|
||||
is_unique = true
|
||||
};
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
@@ -54,50 +45,6 @@ template <typename A, typename K, typename M, typename H, typename P> struct map
|
||||
insert_return_type;
|
||||
};
|
||||
|
||||
template <typename A, typename K, typename M, typename H, typename P>
|
||||
struct multimap
|
||||
{
|
||||
typedef boost::unordered::detail::multimap<A, K, M, H, P> types;
|
||||
|
||||
typedef std::pair<K const, M> value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef K const const_key_type;
|
||||
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<A,
|
||||
value_type>::type value_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES != 1
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::map_extractor<value_type> extractor;
|
||||
enum
|
||||
{
|
||||
is_unique = false
|
||||
};
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<K>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::l_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_map<node, K, M, A> node_type;
|
||||
};
|
||||
|
||||
template <typename K, typename M, typename H, typename P, typename A>
|
||||
class instantiate_map
|
||||
{
|
||||
|
@@ -23,22 +23,13 @@ template <typename A, typename T, typename H, typename P> struct set
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES != 2
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
enum
|
||||
{
|
||||
is_unique = true
|
||||
};
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
@@ -54,49 +45,6 @@ template <typename A, typename T, typename H, typename P> struct set
|
||||
insert_return_type;
|
||||
};
|
||||
|
||||
template <typename A, typename T, typename H, typename P> struct multiset
|
||||
{
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
|
||||
typedef T value_type;
|
||||
typedef H hasher;
|
||||
typedef P key_equal;
|
||||
typedef T const const_key_type;
|
||||
|
||||
typedef typename ::boost::unordered::detail::rebind_wrap<A,
|
||||
value_type>::type value_allocator;
|
||||
typedef boost::unordered::detail::allocator_traits<value_allocator>
|
||||
value_allocator_traits;
|
||||
|
||||
#if BOOST_UNORDERED_INTEROPERABLE_NODES != 1
|
||||
typedef boost::unordered::detail::pick_grouped_node<A, value_type> pick;
|
||||
#else
|
||||
typedef boost::unordered::detail::pick_node<A, value_type> pick;
|
||||
#endif
|
||||
typedef typename pick::node node;
|
||||
typedef typename pick::bucket bucket;
|
||||
typedef typename pick::link_pointer link_pointer;
|
||||
typedef typename pick::node_algo node_algo;
|
||||
|
||||
typedef boost::unordered::detail::table<types> table;
|
||||
typedef boost::unordered::detail::set_extractor<value_type> extractor;
|
||||
enum
|
||||
{
|
||||
is_unique = false
|
||||
};
|
||||
|
||||
typedef typename boost::unordered::detail::pick_policy<T>::type policy;
|
||||
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> iterator;
|
||||
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
l_iterator;
|
||||
typedef boost::unordered::iterator_detail::cl_iterator<node, policy>
|
||||
cl_iterator;
|
||||
|
||||
typedef boost::unordered::node_handle_set<node, T, A> node_type;
|
||||
};
|
||||
|
||||
template <typename T, typename H, typename P, typename A> class instantiate_set
|
||||
{
|
||||
typedef boost::unordered_set<T, H, P, A> container;
|
||||
|
@@ -146,7 +146,7 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_map& operator=(BOOST_COPY_ASSIGN_REF(unordered_map) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -156,13 +156,13 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_map& operator=(unordered_map const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -173,7 +173,7 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@@ -740,14 +740,12 @@ template <class K, class T, class H, class P, class A> class unordered_map
|
||||
void merge(boost::unordered_map<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -858,7 +856,7 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
typedef A allocator_type;
|
||||
|
||||
private:
|
||||
typedef boost::unordered::detail::multimap<A, K, T, H, P> types;
|
||||
typedef boost::unordered::detail::map<A, K, T, H, P> types;
|
||||
typedef typename types::value_allocator_traits value_allocator_traits;
|
||||
typedef typename types::table table;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
@@ -952,7 +950,7 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multimap& operator=(BOOST_COPY_ASSIGN_REF(unordered_multimap) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -962,13 +960,13 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multimap& operator=(unordered_multimap const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -979,7 +977,7 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@@ -1277,14 +1275,12 @@ template <class K, class T, class H, class P, class A> class unordered_multimap
|
||||
void merge(boost::unordered_multimap<K, T, H2, P2, A>&& source);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -1573,7 +1569,7 @@ unordered_map<K, T, H, P, A>::erase(iterator position)
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_unique(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -1584,7 +1580,7 @@ unordered_map<K, T, H, P, A>::erase(const_iterator position)
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_unique(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -1644,7 +1640,6 @@ 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(
|
||||
@@ -1662,7 +1657,6 @@ void unordered_map<K, T, H, P, A>::merge(
|
||||
table_.merge_unique(source.table_);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// observers
|
||||
|
||||
@@ -1729,8 +1723,7 @@ std::pair<typename unordered_map<K, T, H, P, A>::iterator,
|
||||
unordered_map<K, T, H, P, A>::equal_range(const key_type& k)
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(
|
||||
iterator(n), iterator(n ? table::node_algo::next_node(n) : n));
|
||||
return std::make_pair(iterator(n), iterator(n ? table::next_node(n) : n));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -1739,8 +1732,8 @@ std::pair<typename unordered_map<K, T, H, P, A>::const_iterator,
|
||||
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(const_iterator(n),
|
||||
const_iterator(n ? table::node_algo::next_node(n) : n));
|
||||
return std::make_pair(
|
||||
const_iterator(n), const_iterator(n ? table::next_node(n) : n));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -2060,7 +2053,7 @@ unordered_multimap<K, T, H, P, A>::erase(iterator position)
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_equiv(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -2071,7 +2064,7 @@ unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_equiv(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -2152,7 +2145,6 @@ 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(
|
||||
@@ -2174,7 +2166,6 @@ void unordered_multimap<K, T, H, P, A>::merge(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
@@ -2217,7 +2208,7 @@ typename unordered_multimap<K, T, H, P, A>::size_type
|
||||
unordered_multimap<K, T, H, P, A>::count(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return n ? table::node_algo::count(n, &table_) : 0;
|
||||
return n ? table_.group_count(n) : 0;
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -2226,8 +2217,7 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::iterator,
|
||||
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k)
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(iterator(n),
|
||||
iterator(n ? table::node_algo::next_group(n, &table_) : n));
|
||||
return std::make_pair(iterator(n), iterator(n ? table_.next_group(n) : n));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
@@ -2236,8 +2226,8 @@ std::pair<typename unordered_multimap<K, T, H, P, A>::const_iterator,
|
||||
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(const_iterator(n),
|
||||
const_iterator(n ? table::node_algo::next_group(n, &table_) : n));
|
||||
return std::make_pair(
|
||||
const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
|
||||
}
|
||||
|
||||
template <class K, class T, class H, class P, class A>
|
||||
|
@@ -144,7 +144,7 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_set& operator=(BOOST_COPY_ASSIGN_REF(unordered_set) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -154,13 +154,13 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_set& operator=(unordered_set const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, true);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@@ -457,14 +457,12 @@ template <class T, class H, class P, class A> class unordered_set
|
||||
void merge(boost::unordered_set<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -562,7 +560,7 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
typedef A allocator_type;
|
||||
|
||||
private:
|
||||
typedef boost::unordered::detail::multiset<A, T, H, P> types;
|
||||
typedef boost::unordered::detail::set<A, T, H, P> types;
|
||||
typedef typename types::value_allocator_traits value_allocator_traits;
|
||||
typedef typename types::table table;
|
||||
typedef typename table::node_pointer node_pointer;
|
||||
@@ -656,7 +654,7 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
#if defined(BOOST_UNORDERED_USE_MOVE)
|
||||
unordered_multiset& operator=(BOOST_COPY_ASSIGN_REF(unordered_multiset) x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -666,13 +664,13 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
unordered_multiset& operator=(unordered_multiset const& x)
|
||||
{
|
||||
table_.assign(x.table_);
|
||||
table_.assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -683,7 +681,7 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
// is_nothrow_move_assignable_v<H> &&
|
||||
// is_nothrow_move_assignable_v<P>)
|
||||
{
|
||||
table_.move_assign(x.table_);
|
||||
table_.move_assign(x.table_, false);
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
@@ -962,14 +960,12 @@ template <class T, class H, class P, class A> class unordered_multiset
|
||||
void merge(boost::unordered_multiset<T, H2, P2, A>&& source);
|
||||
#endif
|
||||
|
||||
#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
|
||||
@@ -1246,7 +1242,7 @@ typename unordered_set<T, H, P, A>::iterator unordered_set<T, H, P, A>::erase(
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_unique(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -1322,7 +1318,6 @@ 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(
|
||||
@@ -1340,7 +1335,6 @@ void unordered_set<T, H, P, A>::merge(
|
||||
table_.merge_unique(source.table_);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
@@ -1374,8 +1368,8 @@ std::pair<typename unordered_set<T, H, P, A>::const_iterator,
|
||||
unordered_set<T, H, P, A>::equal_range(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(const_iterator(n),
|
||||
const_iterator(n ? table::node_algo::next_node(n) : n));
|
||||
return std::make_pair(
|
||||
const_iterator(n), const_iterator(n ? table::next_node(n) : n));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1652,7 +1646,7 @@ unordered_multiset<T, H, P, A>::erase(const_iterator position)
|
||||
{
|
||||
node_pointer node = table::get_node(position);
|
||||
BOOST_ASSERT(node);
|
||||
node_pointer next = table::node_algo::next_node(node);
|
||||
node_pointer next = table::next_node(node);
|
||||
table_.erase_nodes_equiv(node, next);
|
||||
return iterator(next);
|
||||
}
|
||||
@@ -1732,7 +1726,6 @@ 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(
|
||||
@@ -1754,7 +1747,6 @@ void unordered_multiset<T, H, P, A>::merge(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// lookup
|
||||
|
||||
@@ -1780,7 +1772,7 @@ typename unordered_multiset<T, H, P, A>::size_type
|
||||
unordered_multiset<T, H, P, A>::count(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return n ? table::node_algo::count(n, &table_) : 0;
|
||||
return n ? table_.group_count(n) : 0;
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
@@ -1789,8 +1781,8 @@ std::pair<typename unordered_multiset<T, H, P, A>::const_iterator,
|
||||
unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
|
||||
{
|
||||
node_pointer n = table_.find_node(k);
|
||||
return std::make_pair(const_iterator(n),
|
||||
const_iterator(n ? table::node_algo::next_group(n, &table_) : n));
|
||||
return std::make_pair(
|
||||
const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
|
||||
}
|
||||
|
||||
template <class T, class H, class P, class A>
|
||||
|
@@ -63,10 +63,17 @@ template <class X> void check_equivalent_keys(X const& x1)
|
||||
BOOST_DEDUCED_TYPENAME X::size_type bucket = x1.bucket(key);
|
||||
BOOST_DEDUCED_TYPENAME X::const_local_iterator lit = x1.begin(bucket),
|
||||
lend = x1.end(bucket);
|
||||
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit)
|
||||
continue;
|
||||
if (lit == lend)
|
||||
|
||||
unsigned int count_checked = 0;
|
||||
for (; lit != lend && !eq(get_key<X>(*lit), key); ++lit) {
|
||||
++count_checked;
|
||||
}
|
||||
|
||||
if (lit == lend) {
|
||||
BOOST_ERROR("Unable to find element with a local_iterator");
|
||||
std::cerr << "Checked: " << count_checked << " elements"
|
||||
<< std::endl;
|
||||
} else {
|
||||
unsigned int count2 = 0;
|
||||
for (; lit != lend && eq(get_key<X>(*lit), key); ++lit)
|
||||
++count2;
|
||||
@@ -79,6 +86,7 @@ template <class X> void check_equivalent_keys(X const& x1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Check that size matches up.
|
||||
|
@@ -93,8 +93,6 @@ static inline void run_tests()
|
||||
<< BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT << "\n" \
|
||||
<< "BOOST_UNORDERED_EMPLACE_LIMIT: " \
|
||||
<< BOOST_UNORDERED_EMPLACE_LIMIT << "\n" \
|
||||
<< "BOOST_UNORDERED_INTEROPERABLE_NODES: " \
|
||||
<< BOOST_UNORDERED_INTEROPERABLE_NODES << "\n" \
|
||||
<< "BOOST_UNORDERED_USE_ALLOCATOR_TRAITS: " \
|
||||
<< BOOST_UNORDERED_USE_ALLOCATOR_TRAITS << "\n" \
|
||||
<< "BOOST_UNORDERED_CXX11_CONSTRUCTION: " \
|
||||
|
@@ -47,9 +47,9 @@ std::size_t hash_value(insert_stable::member const& x)
|
||||
}
|
||||
}
|
||||
|
||||
// This is now only supported when using grouped nodes. I can't see any
|
||||
// efficient way to do it otherwise.
|
||||
#if !BOOST_UNORDERED_INTEROPERABLE_NODES
|
||||
// This is no longer supported, as there's no longer an efficient way to get to
|
||||
// the end of a group of equivalent nodes.
|
||||
#if 0
|
||||
|
||||
UNORDERED_AUTO_TEST(stable_insert_test1)
|
||||
{
|
||||
|
@@ -99,7 +99,6 @@ 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;
|
||||
@@ -139,7 +138,6 @@ UNORDERED_AUTO_TEST(merge_set_and_multiset)
|
||||
test::check_equivalent_keys(x);
|
||||
test::check_equivalent_keys(y);
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class X> void merge_empty_test(X*, test::random_generator generator)
|
||||
{
|
||||
|
Reference in New Issue
Block a user