Refactor internal implementation to use "fast closed-addressing" aka fca

This commit is contained in:
Christian Mazakas
2022-05-20 14:33:35 -07:00
parent ad639ffb61
commit 5a456eb295
9 changed files with 2251 additions and 2153 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2005-2016 Daniel James // Copyright (C) 2005-2016 Daniel James
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -25,25 +26,18 @@ namespace boost {
typedef boost::unordered::detail::allocator_traits<value_allocator> typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits; value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table; typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::map_extractor<value_type> extractor; typedef boost::unordered::detail::map_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<K>::type policy; typedef typename boost::allocator_void_pointer<value_allocator>::type
void_pointer;
typedef boost::unordered::iterator_detail::iterator<node> iterator; typedef boost::unordered::node_handle_map<
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator; node<value_type, void_pointer>, K, M, A>
typedef boost::unordered::iterator_detail::l_iterator<node> l_iterator; node_type;
typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_map<node, K, M, A> node_type; typedef typename table::iterator iterator;
typedef boost::unordered::insert_return_type_map<node, K, M, A> typedef boost::unordered::insert_return_type_map<iterator, node_type> insert_return_type;
insert_return_type;
}; };
template <typename K, typename M, typename H, typename P, typename A> template <typename K, typename M, typename H, typename P, typename A>

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2005-2016 Daniel James // Copyright (C) 2005-2016 Daniel James
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -24,24 +25,18 @@ namespace boost {
typedef boost::unordered::detail::allocator_traits<value_allocator> typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits; value_allocator_traits;
typedef boost::unordered::detail::pick_node<A, value_type> pick;
typedef typename pick::node node;
typedef typename pick::bucket bucket;
typedef typename pick::link_pointer link_pointer;
typedef boost::unordered::detail::table<types> table; typedef boost::unordered::detail::table<types> table;
typedef boost::unordered::detail::set_extractor<value_type> extractor; typedef boost::unordered::detail::set_extractor<value_type> extractor;
typedef typename boost::unordered::detail::pick_policy<T>::type policy; typedef typename boost::allocator_void_pointer<value_allocator>::type
void_pointer;
typedef boost::unordered::iterator_detail::c_iterator<node> iterator; typedef boost::unordered::node_handle_set<
typedef boost::unordered::iterator_detail::c_iterator<node> c_iterator; node<value_type, void_pointer>, T, A>
typedef boost::unordered::iterator_detail::cl_iterator<node> l_iterator; node_type;
typedef boost::unordered::iterator_detail::cl_iterator<node>
cl_iterator;
typedef boost::unordered::node_handle_set<node, T, A> node_type; typedef typename table::c_iterator iterator;
typedef boost::unordered::insert_return_type_set<node, T, A> typedef boost::unordered::insert_return_type_set<iterator, node_type>
insert_return_type; insert_return_type;
}; };

View File

@@ -1,6 +1,7 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2011 Daniel James. // Copyright (C) 2005-2011 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -57,8 +58,6 @@ namespace boost {
typedef boost::unordered::detail::map<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::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@@ -188,9 +187,9 @@ namespace boost {
return table_.node_alloc(); return table_.node_alloc();
} }
// iterators // // iterators
iterator begin() BOOST_NOEXCEPT { return iterator(table_.begin()); } iterator begin() BOOST_NOEXCEPT { return table_.begin(); }
const_iterator begin() const BOOST_NOEXCEPT const_iterator begin() const BOOST_NOEXCEPT
{ {
@@ -445,7 +444,7 @@ namespace boost {
insert_return_type insert(BOOST_RV_REF(node_type) np) insert_return_type insert(BOOST_RV_REF(node_type) np)
{ {
insert_return_type result; insert_return_type result;
table_.move_insert_node_type_unique(np, result); table_.move_insert_node_type_unique((node_type&)np, result);
return boost::move(result); return boost::move(result);
} }
@@ -728,8 +727,7 @@ namespace boost {
size_type>::type size_type>::type
erase(BOOST_FWD_REF(Key) k) erase(BOOST_FWD_REF(Key) k)
{ {
return table_.erase_key_unique_impl( return table_.erase_key_unique_impl(boost::forward<Key>(k));
this->key_eq(), boost::forward<Key>(k));
} }
BOOST_UNORDERED_DEPRECATED("Use erase instead") BOOST_UNORDERED_DEPRECATED("Use erase instead")
@@ -774,9 +772,7 @@ namespace boost {
iterator>::type iterator>::type
find(const Key& key) find(const Key& key)
{ {
return iterator(table_.find_node_impl( return table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key,
this->key_eq()));
} }
template <class Key> template <class Key>
@@ -784,9 +780,7 @@ namespace boost {
const_iterator>::type const_iterator>::type
find(const Key& key) const find(const Key& key) const
{ {
return const_iterator(table_.find_node_impl( return const_iterator(table_.find(key));
table::policy::apply_hash(this->hash_function(), key), key,
this->key_eq()));
} }
template <class CompatibleKey, class CompatibleHash, template <class CompatibleKey, class CompatibleHash,
@@ -801,9 +795,7 @@ namespace boost {
bool contains(const key_type& k) const bool contains(const key_type& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
template <class Key> template <class Key>
@@ -811,9 +803,7 @@ namespace boost {
bool>::type bool>::type
contains(const Key& k) const contains(const Key& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
size_type count(const key_type&) const; size_type count(const key_type&) const;
@@ -823,14 +813,7 @@ namespace boost {
size_type>::type size_type>::type
count(const Key& k) const count(const Key& k) const
{ {
std::size_t const key_hash = return (table_.find(k) != this->end() ? 1 : 0);
table::policy::apply_hash(this->hash_function(), k);
P const& eq = this->key_eq();
node_pointer p = table_.find_node_impl(key_hash, k, eq);
return (p ? 1 : 0);
} }
std::pair<iterator, iterator> equal_range(const key_type&); std::pair<iterator, iterator> equal_range(const key_type&);
@@ -842,12 +825,13 @@ namespace boost {
std::pair<iterator, iterator> >::type std::pair<iterator, iterator> >::type
equal_range(const Key& key) equal_range(const Key& key)
{ {
node_pointer p = table_.find_node_impl( iterator first = table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key, iterator last = first;
this->key_eq()); if (last != this->end()) {
++last;
}
return std::make_pair( return std::make_pair(first, last);
iterator(p), iterator(p ? table::next_node(p) : p));
} }
template <class Key> template <class Key>
@@ -855,12 +839,13 @@ namespace boost {
std::pair<const_iterator, const_iterator> >::type std::pair<const_iterator, const_iterator> >::type
equal_range(const Key& key) const equal_range(const Key& key) const
{ {
node_pointer p = table_.find_node_impl( iterator first = table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key, iterator last = first;
this->key_eq()); if (last != this->end()) {
++last;
}
return std::make_pair( return std::make_pair(first, last);
const_iterator(p), const_iterator(p ? table::next_node(p) : p));
} }
mapped_type& operator[](const key_type&); mapped_type& operator[](const key_type&);
@@ -872,7 +857,7 @@ namespace boost {
size_type bucket_count() const BOOST_NOEXCEPT size_type bucket_count() const BOOST_NOEXCEPT
{ {
return table_.bucket_count_; return table_.bucket_count();
} }
size_type max_bucket_count() const BOOST_NOEXCEPT size_type max_bucket_count() const BOOST_NOEXCEPT
@@ -889,16 +874,15 @@ namespace boost {
local_iterator begin(size_type n) local_iterator begin(size_type n)
{ {
return local_iterator(table_.begin(n), n, table_.bucket_count_); return table_.begin(n);
} }
const_local_iterator begin(size_type n) const const_local_iterator begin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
local_iterator end(size_type) { return local_iterator(); } local_iterator end(size_type) { return local_iterator(); }
const_local_iterator end(size_type) const const_local_iterator end(size_type) const
{ {
return const_local_iterator(); return const_local_iterator();
@@ -906,7 +890,7 @@ namespace boost {
const_local_iterator cbegin(size_type n) const const_local_iterator cbegin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
const_local_iterator cend(size_type) const const_local_iterator cend(size_type) const
@@ -1026,8 +1010,6 @@ namespace boost {
typedef boost::unordered::detail::map<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::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@@ -1394,7 +1376,7 @@ namespace boost {
node_type extract(const key_type& k) node_type extract(const key_type& k)
{ {
return node_type(table_.extract_by_key(k), table_.node_alloc()); return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
} }
template <class Key> template <class Key>
@@ -1437,8 +1419,7 @@ namespace boost {
size_type>::type size_type>::type
erase(BOOST_FWD_REF(Key) k) erase(BOOST_FWD_REF(Key) k)
{ {
return table_.erase_key_equiv_impl( return table_.erase_key_equiv_impl(boost::forward<Key>(k));
this->key_eq(), boost::forward<Key>(k));
} }
BOOST_UNORDERED_DEPRECATED("Use erase instead") BOOST_UNORDERED_DEPRECATED("Use erase instead")
@@ -1483,9 +1464,7 @@ namespace boost {
iterator>::type iterator>::type
find(const Key& key) find(const Key& key)
{ {
return iterator(table_.find_node_impl( return table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key,
this->key_eq()));
} }
template <class Key> template <class Key>
@@ -1493,9 +1472,7 @@ namespace boost {
const_iterator>::type const_iterator>::type
find(const Key& key) const find(const Key& key) const
{ {
return const_iterator(table_.find_node_impl( return const_iterator(table_.find(key));
table::policy::apply_hash(this->hash_function(), key), key,
this->key_eq()));
} }
template <class CompatibleKey, class CompatibleHash, template <class CompatibleKey, class CompatibleHash,
@@ -1510,9 +1487,7 @@ namespace boost {
bool contains(key_type const& k) const bool contains(key_type const& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
template <class Key> template <class Key>
@@ -1520,9 +1495,7 @@ namespace boost {
bool>::type bool>::type
contains(const Key& k) const contains(const Key& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
size_type count(const key_type&) const; size_type count(const key_type&) const;
@@ -1532,11 +1505,7 @@ namespace boost {
size_type>::type size_type>::type
count(const Key& k) const count(const Key& k) const
{ {
node_pointer n = table_.find_node_impl( return table_.group_count(k);
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
return n ? table_.group_count(n) : 0;
} }
std::pair<iterator, iterator> equal_range(const key_type&); std::pair<iterator, iterator> equal_range(const key_type&);
@@ -1548,12 +1517,8 @@ namespace boost {
std::pair<iterator, iterator> >::type std::pair<iterator, iterator> >::type
equal_range(const Key& key) equal_range(const Key& key)
{ {
node_pointer p = table_.find_node_impl( iterator p = table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key, return std::make_pair(p, table_.next_group(key, p));
this->key_eq());
return std::make_pair(
iterator(p), iterator(p ? table_.next_group(p) : p));
} }
template <class Key> template <class Key>
@@ -1561,19 +1526,16 @@ namespace boost {
std::pair<const_iterator, const_iterator> >::type std::pair<const_iterator, const_iterator> >::type
equal_range(const Key& key) const equal_range(const Key& key) const
{ {
node_pointer p = table_.find_node_impl( iterator p = table_.find(key);
table::policy::apply_hash(this->hash_function(), key), key,
this->key_eq());
return std::make_pair( return std::make_pair(
const_iterator(p), const_iterator(p ? table_.next_group(p) : p)); const_iterator(p), const_iterator(table_.next_group(key, p)));
} }
// bucket interface // bucket interface
size_type bucket_count() const BOOST_NOEXCEPT size_type bucket_count() const BOOST_NOEXCEPT
{ {
return table_.bucket_count_; return table_.bucket_count();
} }
size_type max_bucket_count() const BOOST_NOEXCEPT size_type max_bucket_count() const BOOST_NOEXCEPT
@@ -1590,12 +1552,12 @@ namespace boost {
local_iterator begin(size_type n) local_iterator begin(size_type n)
{ {
return local_iterator(table_.begin(n), n, table_.bucket_count_); return local_iterator(table_.begin(n));
} }
const_local_iterator begin(size_type n) const const_local_iterator begin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
local_iterator end(size_type) { return local_iterator(); } local_iterator end(size_type) { return local_iterator(); }
@@ -1607,7 +1569,7 @@ namespace boost {
const_local_iterator cbegin(size_type n) const const_local_iterator cbegin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
const_local_iterator cend(size_type) const const_local_iterator cend(size_type) const
@@ -1730,7 +1692,7 @@ namespace boost {
unordered_map::value_allocator_traits:: unordered_map::value_allocator_traits::
select_on_container_copy_construction(other.get_allocator())) select_on_container_copy_construction(other.get_allocator()))
{ {
if (other.table_.size_) { if (other.size()) {
table_.copy_buckets( table_.copy_buckets(
other.table_, boost::unordered::detail::true_type()); other.table_, boost::unordered::detail::true_type());
} }
@@ -1894,29 +1856,25 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(iterator position) unordered_map<K, T, H, P, A>::erase(iterator position)
{ {
node_pointer node = table::get_node(position); const_iterator last = position;
BOOST_ASSERT(node); ++last;
node_pointer next = table::next_node(node); return table_.erase_nodes_range(position, last);
table_.erase_nodes_unique(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::erase(const_iterator position) unordered_map<K, T, H, P, A>::erase(const_iterator position)
{ {
node_pointer node = table::get_node(position); const_iterator last = position;
BOOST_ASSERT(node); ++last;
node_pointer next = table::next_node(node); return table_.erase_nodes_range(position, last);
table_.erase_nodes_unique(node, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::size_type typename unordered_map<K, T, H, P, A>::size_type
unordered_map<K, T, H, P, A>::erase(const key_type& k) unordered_map<K, T, H, P, A>::erase(const key_type& k)
{ {
return table_.erase_key_unique_impl(this->key_eq(), k); return table_.erase_key_unique_impl(k);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -1924,11 +1882,7 @@ namespace boost {
unordered_map<K, T, H, P, A>::erase( unordered_map<K, T, H, P, A>::erase(
const_iterator first, const_iterator last) const_iterator first, const_iterator last)
{ {
node_pointer last_node = table::get_node(last); return table_.erase_nodes_range(first, last);
if (first == last)
return iterator(last_node);
table_.erase_nodes_unique(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -1998,14 +1952,14 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::iterator typename unordered_map<K, T, H, P, A>::iterator
unordered_map<K, T, H, P, A>::find(const key_type& k) unordered_map<K, T, H, P, A>::find(const key_type& k)
{ {
return iterator(table_.find_node(k)); return iterator(table_.find(k));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_map<K, T, H, P, A>::const_iterator typename unordered_map<K, T, H, P, A>::const_iterator
unordered_map<K, T, H, P, A>::find(const key_type& k) const unordered_map<K, T, H, P, A>::find(const key_type& k) const
{ {
return const_iterator(table_.find_node(k)); return const_iterator(table_.find(k));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2015,8 +1969,7 @@ namespace boost {
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k, unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) CompatibleHash const& hash, CompatiblePredicate const& eq)
{ {
return iterator( return table_.transparent_find(k, hash, eq);
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2026,8 +1979,7 @@ namespace boost {
unordered_map<K, T, H, P, A>::find(CompatibleKey const& k, unordered_map<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator( return table_.transparent_find(k, hash, eq);
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2042,8 +1994,12 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::iterator> typename unordered_map<K, T, H, P, A>::iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) unordered_map<K, T, H, P, A>::equal_range(const key_type& k)
{ {
node_pointer n = table_.find_node(k); iterator first = table_.find(k);
return std::make_pair(iterator(n), iterator(n ? table::next_node(n) : n)); iterator second = first;
if (second != this->end()) {
++second;
}
return std::make_pair(first, second);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2051,9 +2007,12 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::const_iterator> typename unordered_map<K, T, H, P, A>::const_iterator>
unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const unordered_map<K, T, H, P, A>::equal_range(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); iterator first = table_.find(k);
return std::make_pair( iterator second = first;
const_iterator(n), const_iterator(n ? table::next_node(n) : n)); if (second != this->end()) {
++second;
}
return std::make_pair(const_iterator(first), const_iterator(second));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2074,10 +2033,12 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::mapped_type& typename unordered_map<K, T, H, P, A>::mapped_type&
unordered_map<K, T, H, P, A>::at(const key_type& k) unordered_map<K, T, H, P, A>::at(const key_type& k)
{ {
typedef typename table::node_pointer node_pointer;
if (table_.size_) { if (table_.size_) {
node_pointer n = table_.find_node(k); node_pointer p = table_.find_node(k);
if (n) if (p)
return n->value().second; return p->value().second;
} }
boost::throw_exception( boost::throw_exception(
@@ -2088,10 +2049,12 @@ namespace boost {
typename unordered_map<K, T, H, P, A>::mapped_type const& typename unordered_map<K, T, H, P, A>::mapped_type const&
unordered_map<K, T, H, P, A>::at(const key_type& k) const unordered_map<K, T, H, P, A>::at(const key_type& k) const
{ {
typedef typename table::node_pointer node_pointer;
if (table_.size_) { if (table_.size_) {
node_pointer n = table_.find_node(k); node_pointer p = table_.find_node(k);
if (n) if (p)
return n->value().second; return p->value().second;
} }
boost::throw_exception( boost::throw_exception(
@@ -2110,9 +2073,9 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_map<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
BOOST_ASSERT(table_.bucket_count_ != 0); BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) / return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_); static_cast<float>(table_.bucket_count());
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2130,8 +2093,7 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_map<K, T, H, P, A>::reserve(size_type n) void unordered_map<K, T, H, P, A>::reserve(size_type n)
{ {
table_.rehash(static_cast<std::size_t>( table_.reserve(n);
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2377,22 +2339,20 @@ namespace boost {
typename unordered_multimap<K, T, H, P, A>::iterator typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(iterator position) unordered_multimap<K, T, H, P, A>::erase(iterator position)
{ {
node_pointer node = table::get_node(position); BOOST_ASSERT(position != this->end());
BOOST_ASSERT(node); iterator next = position;
node_pointer next = table::next_node(node); ++next;
table_.erase_nodes_equiv(node, next); return table_.erase_nodes_range(position, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::iterator typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::erase(const_iterator position) unordered_multimap<K, T, H, P, A>::erase(const_iterator position)
{ {
node_pointer node = table::get_node(position); BOOST_ASSERT(position != this->end());
BOOST_ASSERT(node); const_iterator next = position;
node_pointer next = table::next_node(node); ++next;
table_.erase_nodes_equiv(node, next); return table_.erase_nodes_range(position, next);
return iterator(next);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2407,11 +2367,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A>::erase( unordered_multimap<K, T, H, P, A>::erase(
const_iterator first, const_iterator last) const_iterator first, const_iterator last)
{ {
node_pointer last_node = table::get_node(last); return table_.erase_nodes_range(first, last);
if (first == last)
return iterator(last_node);
table_.erase_nodes_equiv(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2489,14 +2445,14 @@ namespace boost {
typename unordered_multimap<K, T, H, P, A>::iterator typename unordered_multimap<K, T, H, P, A>::iterator
unordered_multimap<K, T, H, P, A>::find(const key_type& k) unordered_multimap<K, T, H, P, A>::find(const key_type& k)
{ {
return iterator(table_.find_node(k)); return iterator(table_.find(k));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
typename unordered_multimap<K, T, H, P, A>::const_iterator typename unordered_multimap<K, T, H, P, A>::const_iterator
unordered_multimap<K, T, H, P, A>::find(const key_type& k) const unordered_multimap<K, T, H, P, A>::find(const key_type& k) const
{ {
return const_iterator(table_.find_node(k)); return const_iterator(table_.find(k));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2506,8 +2462,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k, unordered_multimap<K, T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) CompatibleHash const& hash, CompatiblePredicate const& eq)
{ {
return iterator( return table_.transparent_find(k, hash, eq);
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2525,8 +2480,7 @@ namespace boost {
typename unordered_multimap<K, T, H, P, A>::size_type typename unordered_multimap<K, T, H, P, A>::size_type
unordered_multimap<K, T, H, P, A>::count(const key_type& k) const unordered_multimap<K, T, H, P, A>::count(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); return table_.group_count(k);
return n ? table_.group_count(n) : 0;
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2534,9 +2488,8 @@ namespace boost {
typename unordered_multimap<K, T, H, P, A>::iterator> typename unordered_multimap<K, T, H, P, A>::iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k)
{ {
node_pointer n = table_.find_node(k); iterator n = table_.find(k);
return std::make_pair( return std::make_pair(n, (n == end() ? n : table_.next_group(k, n)));
iterator(n), iterator(n ? table_.next_group(n) : n));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2544,9 +2497,9 @@ namespace boost {
typename unordered_multimap<K, T, H, P, A>::const_iterator> typename unordered_multimap<K, T, H, P, A>::const_iterator>
unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const unordered_multimap<K, T, H, P, A>::equal_range(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); iterator n = table_.find(k);
return std::make_pair( return std::make_pair(const_iterator(n),
const_iterator(n), const_iterator(n ? table_.next_group(n) : n)); const_iterator(n == end() ? n : table_.next_group(k, n)));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2561,9 +2514,9 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_multimap<K, T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
BOOST_ASSERT(table_.bucket_count_ != 0); BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) / return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_); static_cast<float>(table_.bucket_count());
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2582,8 +2535,7 @@ namespace boost {
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
void unordered_multimap<K, T, H, P, A>::reserve(size_type n) void unordered_multimap<K, T, H, P, A>::reserve(size_type n)
{ {
table_.rehash(static_cast<std::size_t>( table_.reserve(n);
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class K, class T, class H, class P, class A> template <class K, class T, class H, class P, class A>
@@ -2643,16 +2595,14 @@ namespace boost {
template <class K2, class T2, class H2, class P2, class A2> template <class K2, class T2, class H2, class P2, class A2>
friend class boost::unordered::unordered_multimap; friend class boost::unordered::unordered_multimap;
typedef typename boost::unordered::detail::rebind_wrap<A, typedef typename boost::allocator_rebind<A, std::pair<K const, T> >::type
std::pair<K const, T> >::type value_allocator; value_allocator;
typedef boost::unordered::detail::allocator_traits<value_allocator>
value_allocator_traits;
typedef N node; typedef N node;
typedef typename boost::unordered::detail::rebind_wrap<A, node>::type typedef typename boost::allocator_rebind<A, node>::type node_allocator;
node_allocator;
typedef boost::unordered::detail::allocator_traits<node_allocator> typedef
node_allocator_traits; typename boost::allocator_pointer<node_allocator>::type node_pointer;
typedef typename node_allocator_traits::pointer node_pointer;
public: public:
typedef K key_type; typedef K key_type;
@@ -2690,8 +2640,8 @@ namespace boost {
node_handle_map& operator=(BOOST_RV_REF(node_handle_map) n) node_handle_map& operator=(BOOST_RV_REF(node_handle_map) n)
{ {
BOOST_ASSERT(!alloc_.has_value() || BOOST_ASSERT(!alloc_.has_value() ||
value_allocator_traits:: boost::allocator_propagate_on_container_move_assignment<
propagate_on_container_move_assignment::value || value_allocator>::type::value ||
(n.alloc_.has_value() && alloc_ == n.alloc_)); (n.alloc_.has_value() && alloc_ == n.alloc_));
if (ptr_) { if (ptr_) {
@@ -2702,8 +2652,8 @@ namespace boost {
} }
if (!alloc_.has_value() || if (!alloc_.has_value() ||
value_allocator_traits::propagate_on_container_move_assignment:: boost::allocator_propagate_on_container_move_assignment<
value) { value_allocator>::type::value) {
alloc_ = boost::move(n.alloc_); alloc_ = boost::move(n.alloc_);
} }
ptr_ = n.ptr_; ptr_ = n.ptr_;
@@ -2731,14 +2681,17 @@ namespace boost {
} }
void swap(node_handle_map& n) BOOST_NOEXCEPT_IF( void swap(node_handle_map& n) BOOST_NOEXCEPT_IF(
value_allocator_traits::propagate_on_container_swap::value || boost::allocator_propagate_on_container_swap<
value_allocator_traits::is_always_equal::value) value_allocator>::type::value ||
boost::allocator_is_always_equal<value_allocator>::type::value)
{ {
BOOST_ASSERT(
!alloc_.has_value() || !n.alloc_.has_value() || BOOST_ASSERT(!alloc_.has_value() || !n.alloc_.has_value() ||
value_allocator_traits::propagate_on_container_swap::value || boost::allocator_propagate_on_container_swap<
value_allocator>::type::value ||
alloc_ == n.alloc_); alloc_ == n.alloc_);
if (value_allocator_traits::propagate_on_container_swap::value || if (boost::allocator_propagate_on_container_swap<
value_allocator>::type::value ||
!alloc_.has_value() || !n.alloc_.has_value()) { !alloc_.has_value() || !n.alloc_.has_value()) {
boost::swap(alloc_, n.alloc_); boost::swap(alloc_, n.alloc_);
} }
@@ -2753,25 +2706,25 @@ namespace boost {
x.swap(y); x.swap(y);
} }
template <class N, class K, class T, class A> struct insert_return_type_map template <class Iter, class NodeType> struct insert_return_type_map
{ {
private: private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_map) BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_map)
typedef typename boost::unordered::detail::rebind_wrap<A, // typedef typename boost::allocator_rebind<A,
std::pair<K const, T> >::type value_allocator; // std::pair<K const, T> >::type value_allocator;
typedef N node_; // typedef N node_;
public: public:
Iter position;
bool inserted; bool inserted;
boost::unordered::iterator_detail::iterator<node_> position; NodeType node;
boost::unordered::node_handle_map<N, K, T, A> node;
insert_return_type_map() : inserted(false), position(), node() {} insert_return_type_map() : position(), inserted(false), node() {}
insert_return_type_map(BOOST_RV_REF(insert_return_type_map) insert_return_type_map(BOOST_RV_REF(insert_return_type_map)
x) BOOST_NOEXCEPT : inserted(x.inserted), x) BOOST_NOEXCEPT : position(x.position),
position(x.position), inserted(x.inserted),
node(boost::move(x.node)) node(boost::move(x.node))
{ {
} }
@@ -2785,9 +2738,9 @@ namespace boost {
} }
}; };
template <class N, class K, class T, class A> template <class Iter, class NodeType>
void swap(insert_return_type_map<N, K, T, A>& x, void swap(insert_return_type_map<Iter, NodeType>& x,
insert_return_type_map<N, K, T, A>& y) insert_return_type_map<Iter, NodeType>& y)
{ {
boost::swap(x.node, y.node); boost::swap(x.node, y.node);
boost::swap(x.inserted, y.inserted); boost::swap(x.inserted, y.inserted);

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2008-2011 Daniel James. // Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -59,7 +60,7 @@ namespace boost {
unordered_multimap<K, T, H, P, A>& c, Predicate pred); unordered_multimap<K, T, H, P, A>& c, Predicate pred);
template <class N, class K, class T, class A> class node_handle_map; template <class N, class K, class T, class A> class node_handle_map;
template <class N, class K, class T, class A> struct insert_return_type_map; template <class Iter, class NodeType> struct insert_return_type_map;
} }
using boost::unordered::unordered_map; using boost::unordered::unordered_map;

View File

@@ -1,6 +1,7 @@
// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. // Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard.
// Copyright (C) 2005-2011 Daniel James. // Copyright (C) 2005-2011 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -55,8 +56,6 @@ namespace boost {
typedef boost::unordered::detail::set<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::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@@ -68,9 +67,9 @@ namespace boost {
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef typename table::iterator iterator; typedef typename table::c_iterator iterator;
typedef typename table::c_iterator const_iterator; typedef typename table::c_iterator const_iterator;
typedef typename table::l_iterator local_iterator; typedef typename table::cl_iterator local_iterator;
typedef typename table::cl_iterator const_local_iterator; typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type; typedef typename types::node_type node_type;
typedef typename types::insert_return_type insert_return_type; typedef typename types::insert_return_type insert_return_type;
@@ -411,7 +410,7 @@ namespace boost {
node_type extract(const key_type& k) node_type extract(const key_type& k)
{ {
return node_type(table_.extract_by_key(k), table_.node_alloc()); return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
} }
template <class Key> template <class Key>
@@ -455,8 +454,7 @@ namespace boost {
size_type>::type size_type>::type
erase(BOOST_FWD_REF(Key) k) erase(BOOST_FWD_REF(Key) k)
{ {
return table_.erase_key_unique_impl( return table_.erase_key_unique_impl(boost::forward<Key>(k));
this->key_eq(), boost::forward<Key>(k));
} }
BOOST_UNORDERED_DEPRECATED("Use erase instead") BOOST_UNORDERED_DEPRECATED("Use erase instead")
@@ -500,9 +498,7 @@ namespace boost {
const_iterator>::type const_iterator>::type
find(const Key& k) const find(const Key& k) const
{ {
return const_iterator(table_.find_node_impl( return const_iterator(table_.find(k));
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq()));
} }
template <class CompatibleKey, class CompatibleHash, template <class CompatibleKey, class CompatibleHash,
@@ -512,9 +508,7 @@ namespace boost {
bool contains(key_type const& k) const bool contains(key_type const& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
template <class Key> template <class Key>
@@ -522,9 +516,7 @@ namespace boost {
bool>::type bool>::type
contains(const Key& k) const contains(const Key& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
size_type count(const key_type&) const; size_type count(const key_type&) const;
@@ -534,11 +526,7 @@ namespace boost {
size_type>::type size_type>::type
count(const Key& k) const count(const Key& k) const
{ {
node_pointer n = table_.find_node_impl( return table_.find(k) != this->end() ? 1 : 0;
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
return n ? 1 : 0;
} }
std::pair<const_iterator, const_iterator> equal_range( std::pair<const_iterator, const_iterator> equal_range(
@@ -549,19 +537,20 @@ namespace boost {
std::pair<const_iterator, const_iterator> >::type std::pair<const_iterator, const_iterator> >::type
equal_range(Key const& k) const equal_range(Key const& k) const
{ {
node_pointer n = table_.find_node_impl( iterator n = table_.find(k);
table::policy::apply_hash(this->hash_function(), k), k, iterator m = n;
this->key_eq()); if (m != this->end()) {
++m;
}
return std::make_pair( return std::make_pair(const_iterator(n), const_iterator(m));
const_iterator(n), const_iterator(n ? table::next_node(n) : n));
} }
// bucket interface // bucket interface
size_type bucket_count() const BOOST_NOEXCEPT size_type bucket_count() const BOOST_NOEXCEPT
{ {
return table_.bucket_count_; return table_.bucket_count();
} }
size_type max_bucket_count() const BOOST_NOEXCEPT size_type max_bucket_count() const BOOST_NOEXCEPT
@@ -578,12 +567,12 @@ namespace boost {
local_iterator begin(size_type n) local_iterator begin(size_type n)
{ {
return local_iterator(table_.begin(n), n, table_.bucket_count_); return local_iterator(table_.begin(n));
} }
const_local_iterator begin(size_type n) const const_local_iterator begin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
local_iterator end(size_type) { return local_iterator(); } local_iterator end(size_type) { return local_iterator(); }
@@ -595,7 +584,7 @@ namespace boost {
const_local_iterator cbegin(size_type n) const const_local_iterator cbegin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
const_local_iterator cend(size_type) const const_local_iterator cend(size_type) const
@@ -684,8 +673,6 @@ namespace boost {
typedef boost::unordered::detail::set<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::value_allocator_traits value_allocator_traits;
typedef typename types::table table; typedef typename types::table table;
typedef typename table::node_pointer node_pointer;
typedef typename table::link_pointer link_pointer;
public: public:
typedef typename value_allocator_traits::pointer pointer; typedef typename value_allocator_traits::pointer pointer;
@@ -697,9 +684,9 @@ namespace boost {
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
typedef typename table::iterator iterator; typedef typename table::c_iterator iterator;
typedef typename table::c_iterator const_iterator; typedef typename table::c_iterator const_iterator;
typedef typename table::l_iterator local_iterator; typedef typename table::cl_iterator local_iterator;
typedef typename table::cl_iterator const_local_iterator; typedef typename table::cl_iterator const_local_iterator;
typedef typename types::node_type node_type; typedef typename types::node_type node_type;
@@ -1035,7 +1022,7 @@ namespace boost {
node_type extract(const key_type& k) node_type extract(const key_type& k)
{ {
return node_type(table_.extract_by_key(k), table_.node_alloc()); return node_type(table_.extract_by_key_impl(k), table_.node_alloc());
} }
template <class Key> template <class Key>
@@ -1076,7 +1063,7 @@ namespace boost {
size_type>::type size_type>::type
erase(const Key& k) erase(const Key& k)
{ {
return table_.erase_key_equiv_impl(this->key_eq(), k); return table_.erase_key_equiv_impl(k);
} }
iterator erase(const_iterator, const_iterator); iterator erase(const_iterator, const_iterator);
@@ -1121,9 +1108,7 @@ namespace boost {
const_iterator>::type const_iterator>::type
find(const Key& k) const find(const Key& k) const
{ {
return const_iterator(table_.find_node_impl( return table_.find(k);
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq()));
} }
template <class CompatibleKey, class CompatibleHash, template <class CompatibleKey, class CompatibleHash,
@@ -1133,9 +1118,7 @@ namespace boost {
bool contains(const key_type& k) const bool contains(const key_type& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
template <class Key> template <class Key>
@@ -1143,9 +1126,7 @@ namespace boost {
bool>::type bool>::type
contains(const Key& k) const contains(const Key& k) const
{ {
return 0 != table_.find_node_impl( return table_.find(k) != this->end();
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
} }
size_type count(const key_type&) const; size_type count(const key_type&) const;
@@ -1155,11 +1136,7 @@ namespace boost {
size_type>::type size_type>::type
count(const Key& k) const count(const Key& k) const
{ {
node_pointer n = table_.find_node_impl( return table_.group_count(k);
table::policy::apply_hash(this->hash_function(), k), k,
this->key_eq());
return n ? table_.group_count(n) : 0;
} }
std::pair<const_iterator, const_iterator> equal_range( std::pair<const_iterator, const_iterator> equal_range(
@@ -1170,19 +1147,16 @@ namespace boost {
std::pair<const_iterator, const_iterator> >::type std::pair<const_iterator, const_iterator> >::type
equal_range(const Key& k) const equal_range(const Key& k) const
{ {
node_pointer n = table_.find_node_impl( iterator first = table_.find(k);
table::policy::apply_hash(this->hash_function(), k), k, iterator last = table_.next_group(k, first);
this->key_eq()); return std::make_pair(const_iterator(first), const_iterator(last));
return std::make_pair(
const_iterator(n), const_iterator(n ? table_.next_group(n) : n));
} }
// bucket interface // bucket interface
size_type bucket_count() const BOOST_NOEXCEPT size_type bucket_count() const BOOST_NOEXCEPT
{ {
return table_.bucket_count_; return table_.bucket_count();
} }
size_type max_bucket_count() const BOOST_NOEXCEPT size_type max_bucket_count() const BOOST_NOEXCEPT
@@ -1199,12 +1173,12 @@ namespace boost {
local_iterator begin(size_type n) local_iterator begin(size_type n)
{ {
return local_iterator(table_.begin(n), n, table_.bucket_count_); return local_iterator(table_.begin(n));
} }
const_local_iterator begin(size_type n) const const_local_iterator begin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
local_iterator end(size_type) { return local_iterator(); } local_iterator end(size_type) { return local_iterator(); }
@@ -1216,7 +1190,7 @@ namespace boost {
const_local_iterator cbegin(size_type n) const const_local_iterator cbegin(size_type n) const
{ {
return const_local_iterator(table_.begin(n), n, table_.bucket_count_); return const_local_iterator(table_.begin(n));
} }
const_local_iterator cend(size_type) const const_local_iterator cend(size_type) const
@@ -1319,7 +1293,7 @@ namespace boost {
unordered_set::value_allocator_traits:: unordered_set::value_allocator_traits::
select_on_container_copy_construction(other.get_allocator())) select_on_container_copy_construction(other.get_allocator()))
{ {
if (other.table_.size_) { if (other.size()) {
table_.copy_buckets( table_.copy_buckets(
other.table_, boost::unordered::detail::true_type()); other.table_, boost::unordered::detail::true_type());
} }
@@ -1483,29 +1457,23 @@ namespace boost {
typename unordered_set<T, H, P, A>::iterator typename unordered_set<T, H, P, A>::iterator
unordered_set<T, H, P, A>::erase(const_iterator position) unordered_set<T, H, P, A>::erase(const_iterator position)
{ {
node_pointer node = table::get_node(position); const_iterator last = position;
BOOST_ASSERT(node); ++last;
node_pointer next = table::next_node(node); return table_.erase_nodes_range(position, last);
table_.erase_nodes_unique(node, next);
return iterator(next);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::size_type typename unordered_set<T, H, P, A>::size_type
unordered_set<T, H, P, A>::erase(const key_type& k) unordered_set<T, H, P, A>::erase(const key_type& k)
{ {
return table_.erase_key_unique_impl(this->key_eq(), k); return table_.erase_key_unique_impl(k);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
typename unordered_set<T, H, P, A>::iterator typename unordered_set<T, H, P, A>::iterator
unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last) unordered_set<T, H, P, A>::erase(const_iterator first, const_iterator last)
{ {
node_pointer last_node = table::get_node(last); return table_.erase_nodes_range(first, last);
if (first == last)
return iterator(last_node);
table_.erase_nodes_unique(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1575,7 +1543,7 @@ namespace boost {
typename unordered_set<T, H, P, A>::const_iterator typename unordered_set<T, H, P, A>::const_iterator
unordered_set<T, H, P, A>::find(const key_type& k) const unordered_set<T, H, P, A>::find(const key_type& k) const
{ {
return const_iterator(table_.find_node(k)); return const_iterator(table_.find(k));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1585,8 +1553,7 @@ namespace boost {
unordered_set<T, H, P, A>::find(CompatibleKey const& k, unordered_set<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator( return table_.transparent_find(k, hash, eq);
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1601,9 +1568,12 @@ namespace boost {
typename unordered_set<T, H, P, A>::const_iterator> typename unordered_set<T, H, P, A>::const_iterator>
unordered_set<T, H, P, A>::equal_range(const key_type& k) const unordered_set<T, H, P, A>::equal_range(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); iterator first = table_.find(k);
return std::make_pair( iterator second = first;
const_iterator(n), const_iterator(n ? table::next_node(n) : n)); if (second != this->end()) {
++second;
}
return std::make_pair(first, second);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1618,9 +1588,9 @@ namespace boost {
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_set<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
BOOST_ASSERT(table_.bucket_count_ != 0); BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) / return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_); static_cast<float>(table_.bucket_count());
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1638,8 +1608,7 @@ namespace boost {
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_set<T, H, P, A>::reserve(size_type n) void unordered_set<T, H, P, A>::reserve(size_type n)
{ {
table_.rehash(static_cast<std::size_t>( table_.reserve(n);
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1883,11 +1852,11 @@ namespace boost {
typename unordered_multiset<T, H, P, A>::iterator typename unordered_multiset<T, H, P, A>::iterator
unordered_multiset<T, H, P, A>::erase(const_iterator position) unordered_multiset<T, H, P, A>::erase(const_iterator position)
{ {
node_pointer node = table::get_node(position); BOOST_ASSERT(position != this->end());
BOOST_ASSERT(node); iterator next = position;
node_pointer next = table::next_node(node); ++next;
table_.erase_nodes_equiv(node, next); table_.erase_nodes_range(position, next);
return iterator(next); return next;
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1902,11 +1871,7 @@ namespace boost {
unordered_multiset<T, H, P, A>::erase( unordered_multiset<T, H, P, A>::erase(
const_iterator first, const_iterator last) const_iterator first, const_iterator last)
{ {
node_pointer last_node = table::get_node(last); return table_.erase_nodes_range(first, last);
if (first == last)
return iterator(last_node);
table_.erase_nodes_equiv(table::get_node(first), last_node);
return iterator(last_node);
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1984,7 +1949,7 @@ namespace boost {
typename unordered_multiset<T, H, P, A>::const_iterator typename unordered_multiset<T, H, P, A>::const_iterator
unordered_multiset<T, H, P, A>::find(const key_type& k) const unordered_multiset<T, H, P, A>::find(const key_type& k) const
{ {
return const_iterator(table_.find_node(k)); return const_iterator(table_.find(k));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -1994,16 +1959,14 @@ namespace boost {
unordered_multiset<T, H, P, A>::find(CompatibleKey const& k, unordered_multiset<T, H, P, A>::find(CompatibleKey const& k,
CompatibleHash const& hash, CompatiblePredicate const& eq) const CompatibleHash const& hash, CompatiblePredicate const& eq) const
{ {
return const_iterator( return table_.transparent_find(k, hash, eq);
table_.find_node_impl(table::policy::apply_hash(hash, k), k, eq));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
typename unordered_multiset<T, H, P, A>::size_type typename unordered_multiset<T, H, P, A>::size_type
unordered_multiset<T, H, P, A>::count(const key_type& k) const unordered_multiset<T, H, P, A>::count(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); return table_.group_count(k);
return n ? table_.group_count(n) : 0;
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -2011,9 +1974,9 @@ namespace boost {
typename unordered_multiset<T, H, P, A>::const_iterator> typename unordered_multiset<T, H, P, A>::const_iterator>
unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const unordered_multiset<T, H, P, A>::equal_range(const key_type& k) const
{ {
node_pointer n = table_.find_node(k); iterator n = table_.find(k);
return std::make_pair( return std::make_pair(const_iterator(n),
const_iterator(n), const_iterator(n ? table_.next_group(n) : n)); const_iterator(n == end() ? n : table_.next_group(k, n)));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -2028,9 +1991,9 @@ namespace boost {
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT float unordered_multiset<T, H, P, A>::load_factor() const BOOST_NOEXCEPT
{ {
BOOST_ASSERT(table_.bucket_count_ != 0); BOOST_ASSERT(table_.bucket_count() != 0);
return static_cast<float>(table_.size_) / return static_cast<float>(table_.size_) /
static_cast<float>(table_.bucket_count_); static_cast<float>(table_.bucket_count());
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -2048,8 +2011,7 @@ namespace boost {
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
void unordered_multiset<T, H, P, A>::reserve(size_type n) void unordered_multiset<T, H, P, A>::reserve(size_type n)
{ {
table_.rehash(static_cast<std::size_t>( table_.reserve(n);
std::ceil(static_cast<double>(n) / table_.mlf_)));
} }
template <class T, class H, class P, class A> template <class T, class H, class P, class A>
@@ -2217,25 +2179,25 @@ namespace boost {
x.swap(y); x.swap(y);
} }
template <typename N, typename T, typename A> struct insert_return_type_set template <class Iter, class NodeType> struct insert_return_type_set
{ {
private: private:
BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_set) BOOST_MOVABLE_BUT_NOT_COPYABLE(insert_return_type_set)
typedef typename boost::unordered::detail::rebind_wrap<A, T>::type // typedef typename boost::unordered::detail::rebind_wrap<A, T>::type
value_allocator; // value_allocator;
typedef N node_; // typedef N node_;
public: public:
Iter position;
bool inserted; bool inserted;
boost::unordered::iterator_detail::c_iterator<node_> position; NodeType node;
boost::unordered::node_handle_set<N, T, A> node;
insert_return_type_set() : inserted(false), position(), node() {} insert_return_type_set() : position(), inserted(false), node() {}
insert_return_type_set(BOOST_RV_REF(insert_return_type_set) insert_return_type_set(BOOST_RV_REF(insert_return_type_set)
x) BOOST_NOEXCEPT : inserted(x.inserted), x) BOOST_NOEXCEPT : position(x.position),
position(x.position), inserted(x.inserted),
node(boost::move(x.node)) node(boost::move(x.node))
{ {
} }
@@ -2249,9 +2211,9 @@ namespace boost {
} }
}; };
template <typename N, typename T, typename A> template <class Iter, class NodeType>
void swap( void swap(
insert_return_type_set<N, T, A>& x, insert_return_type_set<N, T, A>& y) insert_return_type_set<Iter, NodeType>& x, insert_return_type_set<Iter, NodeType>& y)
{ {
boost::swap(x.node, y.node); boost::swap(x.node, y.node);
boost::swap(x.inserted, y.inserted); boost::swap(x.inserted, y.inserted);

View File

@@ -1,5 +1,6 @@
// Copyright (C) 2008-2011 Daniel James. // Copyright (C) 2008-2011 Daniel James.
// Copyright (C) 2022 Christian Mazakas
// Distributed under the Boost Software License, Version 1.0. (See accompanying // 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) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -57,7 +58,7 @@ namespace boost {
unordered_multiset<K, H, P, A>& c, Predicate pred); unordered_multiset<K, H, P, A>& c, Predicate pred);
template <class N, class T, class A> class node_handle_set; template <class N, class T, class A> class node_handle_set;
template <class N, class T, class A> struct insert_return_type_set; template <class Iter, class NodeType> struct insert_return_type_set;
} }
using boost::unordered::unordered_set; using boost::unordered::unordered_set;

View File

@@ -70,13 +70,13 @@ test-suite unordered
[ run unordered/rehash_tests.cpp ] [ run unordered/rehash_tests.cpp ]
[ run unordered/equality_tests.cpp ] [ run unordered/equality_tests.cpp ]
[ run unordered/swap_tests.cpp ] [ run unordered/swap_tests.cpp ]
[ run unordered/detail_tests.cpp ] # [ run unordered/detail_tests.cpp ]
[ run unordered/deduction_tests.cpp ] [ run unordered/deduction_tests.cpp ]
[ run unordered/scoped_allocator.cpp : : : <toolset>msvc-14.0:<build>no ] [ run unordered/scoped_allocator.cpp : : : <toolset>msvc-14.0:<build>no ]
[ run unordered/transparent_tests.cpp ] [ run unordered/transparent_tests.cpp ]
[ run unordered/reserve_tests.cpp ] [ run unordered/reserve_tests.cpp ]
[ run unordered/contains_tests.cpp ] [ run unordered/contains_tests.cpp ]
[ run unordered/mix_policy.cpp ] # [ run unordered/mix_policy.cpp ]
[ run unordered/erase_if.cpp ] [ run unordered/erase_if.cpp ]
[ run unordered/scary_tests.cpp ] [ run unordered/scary_tests.cpp ]