From 77bf2b5e33e173bef22baca90f2e7a603480f776 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Apr 2017 09:46:05 +0100 Subject: [PATCH 1/4] Rename methods to be different for unique/equiv keys So that the implementation can be moved into a single class. Still some other methods to rename. Some methods didn't need to be renamed (e.g. try_emplace is only used with unique keys), but still renamed for consistency. --- .../boost/unordered/detail/implementation.hpp | 211 ++++++++++-------- include/boost/unordered/unordered_map.hpp | 146 ++++++------ include/boost/unordered/unordered_set.hpp | 86 +++---- 3 files changed, 229 insertions(+), 214 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 937b0a0e..d45a11a4 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3624,7 +3624,7 @@ template struct node_algo // Add node 'n' after 'pos'. // This results in a different order to the grouped implementation. - static inline void add_to_node_group(node_pointer n, node_pointer pos) + static inline void add_to_node(node_pointer n, node_pointer pos) { n->next_ = pos->next_; pos->next_ = n; @@ -3761,7 +3761,7 @@ struct table_unique : boost::unordered::detail::table // equals - bool equals(table_unique const& other) const + bool equals_unique(table const& other) const { if (this->size_ != other.size_) return false; @@ -3779,7 +3779,7 @@ struct table_unique : boost::unordered::detail::table // Emplace/Insert - inline node_pointer add_node(node_pointer n, std::size_t key_hash) + inline node_pointer add_node_unique(node_pointer n, std::size_t key_hash) { n->hash_ = key_hash; @@ -3806,27 +3806,28 @@ struct table_unique : boost::unordered::detail::table return n; } - inline node_pointer resize_and_add_node( + inline node_pointer resize_and_add_node_unique( node_pointer n, std::size_t key_hash) { node_tmp b(n, this->node_alloc()); this->reserve_for_insert(this->size_ + 1); - return this->add_node(b.release(), key_hash); + return this->add_node_unique(b.release(), key_hash); } template - iterator emplace_hint_impl( + iterator emplace_hint_unique( c_iterator hint, const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS) { if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) { return iterator(hint.node_); } else { - return emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first; + return emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first; } } template - emplace_return emplace_impl(const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS) + emplace_return emplace_unique( + const_key_type& k, BOOST_UNORDERED_EMPLACE_ARGS) { std::size_t key_hash = this->hash(k); node_pointer pos = this->find_node(key_hash, k); @@ -3834,7 +3835,7 @@ struct table_unique : boost::unordered::detail::table return emplace_return(iterator(pos), false); } else { return emplace_return( - iterator(this->resize_and_add_node( + iterator(this->resize_and_add_node_unique( boost::unordered::detail::func::construct_node_from_args( this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD), key_hash)), @@ -3843,7 +3844,7 @@ struct table_unique : boost::unordered::detail::table } template - iterator emplace_hint_impl( + iterator emplace_hint_unique( c_iterator hint, no_key, BOOST_UNORDERED_EMPLACE_ARGS) { node_tmp b(boost::unordered::detail::func::construct_node_from_args( @@ -3858,12 +3859,13 @@ struct table_unique : boost::unordered::detail::table if (pos) { return iterator(pos); } else { - return iterator(this->resize_and_add_node(b.release(), key_hash)); + return iterator( + this->resize_and_add_node_unique(b.release(), key_hash)); } } template - emplace_return emplace_impl(no_key, BOOST_UNORDERED_EMPLACE_ARGS) + emplace_return emplace_unique(no_key, BOOST_UNORDERED_EMPLACE_ARGS) { node_tmp b(boost::unordered::detail::func::construct_node_from_args( this->node_alloc(), BOOST_UNORDERED_EMPLACE_FORWARD), @@ -3874,14 +3876,14 @@ struct table_unique : boost::unordered::detail::table if (pos) { return emplace_return(iterator(pos), false); } else { - return emplace_return( - iterator(this->resize_and_add_node(b.release(), key_hash)), + return emplace_return(iterator(this->resize_and_add_node_unique( + b.release(), key_hash)), true); } } template - emplace_return try_emplace_impl(BOOST_FWD_REF(Key) k) + emplace_return try_emplace_unique(BOOST_FWD_REF(Key) k) { std::size_t key_hash = this->hash(k); node_pointer pos = this->find_node(key_hash, k); @@ -3889,7 +3891,7 @@ struct table_unique : boost::unordered::detail::table return emplace_return(iterator(pos), false); } else { return emplace_return( - iterator(this->resize_and_add_node( + iterator(this->resize_and_add_node_unique( boost::unordered::detail::func::construct_node_pair( this->node_alloc(), boost::forward(k)), key_hash)), @@ -3898,17 +3900,17 @@ struct table_unique : boost::unordered::detail::table } template - iterator try_emplace_hint_impl(c_iterator hint, BOOST_FWD_REF(Key) k) + iterator try_emplace_hint_unique(c_iterator hint, BOOST_FWD_REF(Key) k) { if (hint.node_ && this->key_eq()(hint->first, k)) { return iterator(hint.node_); } else { - return try_emplace_impl(k).first; + return try_emplace_unique(k).first; } } template - emplace_return try_emplace_impl( + emplace_return try_emplace_unique( BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS) { std::size_t key_hash = this->hash(k); @@ -3917,7 +3919,7 @@ struct table_unique : boost::unordered::detail::table return emplace_return(iterator(pos), false); } else { return emplace_return( - iterator(this->resize_and_add_node( + iterator(this->resize_and_add_node_unique( boost::unordered::detail::func:: construct_node_pair_from_args(this->node_alloc(), boost::forward(k), @@ -3928,18 +3930,18 @@ struct table_unique : boost::unordered::detail::table } template - iterator try_emplace_hint_impl( + iterator try_emplace_hint_unique( c_iterator hint, BOOST_FWD_REF(Key) k, BOOST_UNORDERED_EMPLACE_ARGS) { if (hint.node_ && this->key_eq()(hint->first, k)) { return iterator(hint.node_); } else { - return try_emplace_impl(k, BOOST_UNORDERED_EMPLACE_FORWARD).first; + return try_emplace_unique(k, BOOST_UNORDERED_EMPLACE_FORWARD).first; } } template - emplace_return insert_or_assign_impl( + emplace_return insert_or_assign_unique( BOOST_FWD_REF(Key) k, BOOST_FWD_REF(M) obj) { std::size_t key_hash = this->hash(k); @@ -3950,7 +3952,7 @@ struct table_unique : boost::unordered::detail::table return emplace_return(iterator(pos), false); } else { return emplace_return( - iterator(this->resize_and_add_node( + iterator(this->resize_and_add_node_unique( boost::unordered::detail::func::construct_node_pair( this->node_alloc(), boost::forward(k), boost::forward(obj)), @@ -3960,7 +3962,7 @@ struct table_unique : boost::unordered::detail::table } template - void move_insert_node_type(NodeType& np, InsertReturnType& result) + void move_insert_node_type_unique(NodeType& np, InsertReturnType& result) { if (np) { const_key_type& k = this->get_key(np.ptr_); @@ -3972,7 +3974,8 @@ struct table_unique : boost::unordered::detail::table result.position = iterator(pos); } else { this->reserve_for_insert(this->size_ + 1); - result.position = iterator(this->add_node(np.ptr_, key_hash)); + result.position = + iterator(this->add_node_unique(np.ptr_, key_hash)); result.inserted = true; np.ptr_ = node_pointer(); } @@ -3980,7 +3983,8 @@ struct table_unique : boost::unordered::detail::table } template - iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np) + iterator move_insert_node_type_with_hint_unique( + c_iterator hint, NodeType& np) { if (!np) { return iterator(); @@ -3993,14 +3997,14 @@ struct table_unique : boost::unordered::detail::table node_pointer pos = this->find_node(key_hash, k); if (!pos) { this->reserve_for_insert(this->size_ + 1); - pos = this->add_node(np.ptr_, key_hash); + pos = this->add_node_unique(np.ptr_, key_hash); np.ptr_ = node_pointer(); } return iterator(pos); } template - void merge_impl(boost::unordered::detail::table& other) + void merge_unique(boost::unordered::detail::table& other) { typedef boost::unordered::detail::table other_table; BOOST_STATIC_ASSERT( @@ -4025,7 +4029,7 @@ struct table_unique : boost::unordered::detail::table prev->next_ = n->next_; --other.size_; other.fix_bucket(other.hash_to_bucket(n->hash_), prev); - this->add_node(n, key_hash); + this->add_node_unique(n, key_hash); } } } @@ -4038,20 +4042,20 @@ struct table_unique : boost::unordered::detail::table // safety strong otherwise template - void insert_range_impl(const_key_type& k, InputIt i, InputIt j) + void insert_range_unique(const_key_type& k, InputIt i, InputIt j) { - insert_range_impl2(k, i, j); + insert_range_unique2(k, i, j); while (++i != j) { // Note: can't use get_key as '*i' might not be value_type - it // could be a pair with first_types as key_type without const or // a different second_type. - insert_range_impl2(extractor::extract(*i), i, j); + insert_range_unique2(extractor::extract(*i), i, j); } } template - void insert_range_impl2(const_key_type& k, InputIt i, InputIt j) + void insert_range_unique2(const_key_type& k, InputIt i, InputIt j) { // No side effects in this initial code std::size_t key_hash = this->hash(k); @@ -4064,12 +4068,12 @@ struct table_unique : boost::unordered::detail::table if (this->size_ + 1 > this->max_load_) this->reserve_for_insert( this->size_ + boost::unordered::detail::insert_size(i, j)); - this->add_node(b.release(), key_hash); + this->add_node_unique(b.release(), key_hash); } } template - void insert_range_impl(no_key, InputIt i, InputIt j) + void insert_range_unique(no_key, InputIt i, InputIt j) { node_constructor a(this->node_alloc()); @@ -4091,7 +4095,7 @@ struct table_unique : boost::unordered::detail::table // reserve has basic exception safety if the hash function // throws, strong otherwise. this->reserve_for_insert(this->size_ + 1); - this->add_node(b.release(), key_hash); + this->add_node_unique(b.release(), key_hash); } } while (++i != j); } @@ -4099,7 +4103,7 @@ struct table_unique : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // Extract - inline node_pointer extract_by_iterator(c_iterator i) + inline node_pointer extract_by_iterator_unique(c_iterator i) { node_pointer n = i.node_; BOOST_ASSERT(n); @@ -4121,7 +4125,7 @@ struct table_unique : boost::unordered::detail::table // // no throw - std::size_t erase_key(const_key_type& k) + std::size_t erase_key_unique(const_key_type& k) { if (!this->size_) return 0; @@ -4136,7 +4140,7 @@ struct table_unique : boost::unordered::detail::table return 1; } - void erase_nodes(node_pointer i, node_pointer j) + void erase_nodes_unique(node_pointer i, node_pointer j) { std::size_t bucket_index = this->hash_to_bucket(i->hash_); @@ -4153,15 +4157,16 @@ struct table_unique : boost::unordered::detail::table } //////////////////////////////////////////////////////////////////////// - // fill_buckets + // fill_buckets_unique void copy_buckets(table const& src) { this->create_buckets(this->bucket_count_); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), n->value()), + this->add_node_unique( + boost::unordered::detail::func::construct_node( + this->node_alloc(), n->value()), n->hash_); } } @@ -4171,8 +4176,9 @@ struct table_unique : boost::unordered::detail::table this->create_buckets(this->bucket_count_); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), boost::move(n->value())), + this->add_node_unique( + boost::unordered::detail::func::construct_node( + this->node_alloc(), boost::move(n->value())), n->hash_); } } @@ -4181,7 +4187,7 @@ struct table_unique : boost::unordered::detail::table { node_holder holder(*this); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { - this->add_node(holder.copy_of(n->value()), n->hash_); + this->add_node_unique(holder.copy_of(n->value()), n->hash_); } } @@ -4189,7 +4195,7 @@ struct table_unique : boost::unordered::detail::table { node_holder holder(*this); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { - this->add_node(holder.move_copy_of(n->value()), n->hash_); + this->add_node_unique(holder.move_copy_of(n->value()), n->hash_); } } }; @@ -4297,7 +4303,7 @@ template struct grouped_node_algo // If 'pos' is the first node in group, add to the end of the group, // otherwise add before 'pos'. Other versions will probably behave // differently. - static inline void add_to_node_group(node_pointer n, node_pointer pos) + static inline void add_to_node(node_pointer n, node_pointer pos) { n->next_ = pos->group_prev_->next_; n->group_prev_ = pos->group_prev_; @@ -4458,13 +4464,13 @@ struct table_equiv : boost::unordered::detail::table this->move_buckets_from(x); } else if (x.size_) { // TODO: Could pick new bucket size? - this->move_buckets(x); + this->move_buckets_equiv(x); } } // Equality - bool equals(table_equiv const& other) const + bool equals_equiv(table const& other) const { if (this->size_ != other.size_) return false; @@ -4475,7 +4481,7 @@ struct table_equiv : boost::unordered::detail::table return false; node_pointer end1 = node_algo::next_group(n1, this); node_pointer end2 = node_algo::next_group(n2, this); - if (!group_equals(n1, end1, n2, end2)) + if (!group_equals_equiv(n1, end1, n2, end2)) return false; n1 = end1; } @@ -4483,7 +4489,7 @@ struct table_equiv : boost::unordered::detail::table return true; } - static bool group_equals( + static bool group_equals_equiv( node_pointer n1, node_pointer end1, node_pointer n2, node_pointer end2) { for (;;) { @@ -4517,12 +4523,12 @@ struct table_equiv : boost::unordered::detail::table node_pointer start = n1; for (; n1 != end1; n1 = node_algo::next_node(n1)) { value_type const& v = n1->value(); - if (!find(start, n1, v)) { - std::size_t matches = count_equal(n2, end2, v); + if (!find_equiv(start, n1, v)) { + std::size_t matches = count_equal_equiv(n2, end2, v); if (!matches) return false; if (matches != - 1 + count_equal(node_algo::next_node(n1), end1, v)) + 1 + count_equal_equiv(node_algo::next_node(n1), end1, v)) return false; } } @@ -4530,7 +4536,8 @@ struct table_equiv : boost::unordered::detail::table return true; } - static bool find(node_pointer n, node_pointer end, value_type const& v) + static bool find_equiv( + node_pointer n, node_pointer end, value_type const& v) { for (; n != end; n = node_algo::next_node(n)) if (n->value() == v) @@ -4538,7 +4545,7 @@ struct table_equiv : boost::unordered::detail::table return false; } - static std::size_t count_equal( + static std::size_t count_equal_equiv( node_pointer n, node_pointer end, value_type const& v) { std::size_t count = 0; @@ -4550,12 +4557,12 @@ struct table_equiv : boost::unordered::detail::table // Emplace/Insert - inline node_pointer add_node( + inline node_pointer add_node_equiv( node_pointer n, std::size_t key_hash, node_pointer pos) { n->hash_ = key_hash; if (pos) { - node_algo::add_to_node_group(n, pos); + node_algo::add_to_node(n, pos); if (n->next_) { std::size_t next_bucket = this->hash_to_bucket(node_algo::next_node(n)->hash_); @@ -4588,10 +4595,10 @@ struct table_equiv : boost::unordered::detail::table return n; } - inline node_pointer add_using_hint(node_pointer n, node_pointer hint) + inline node_pointer add_using_hint_equiv(node_pointer n, node_pointer hint) { n->hash_ = hint->hash_; - node_algo::add_to_node_group(n, hint); + node_algo::add_to_node(n, hint); if (n->next_ != hint && n->next_) { std::size_t next_bucket = this->hash_to_bucket(node_algo::next_node(n)->hash_); @@ -4603,41 +4610,44 @@ struct table_equiv : boost::unordered::detail::table return n; } - iterator emplace_impl(node_pointer n) + iterator emplace_equiv(node_pointer n) { node_tmp a(n, this->node_alloc()); const_key_type& k = this->get_key(a.node_); std::size_t key_hash = this->hash(k); node_pointer position = this->find_node(key_hash, k); this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_node(a.release(), key_hash, position)); + return iterator(this->add_node_equiv(a.release(), key_hash, position)); } - iterator emplace_hint_impl(c_iterator hint, node_pointer n) + iterator emplace_hint_equiv(c_iterator hint, node_pointer n) { node_tmp a(n, this->node_alloc()); const_key_type& k = this->get_key(a.node_); if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) { this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_using_hint(a.release(), hint.node_)); + return iterator( + this->add_using_hint_equiv(a.release(), hint.node_)); } else { std::size_t key_hash = this->hash(k); node_pointer position = this->find_node(key_hash, k); this->reserve_for_insert(this->size_ + 1); - return iterator(this->add_node(a.release(), key_hash, position)); + return iterator( + this->add_node_equiv(a.release(), key_hash, position)); } } - void emplace_impl_no_rehash(node_pointer n) + void emplace_no_rehash_equiv(node_pointer n) { node_tmp a(n, this->node_alloc()); const_key_type& k = this->get_key(a.node_); std::size_t key_hash = this->hash(k); node_pointer position = this->find_node(key_hash, k); - this->add_node(a.release(), key_hash, position); + this->add_node_equiv(a.release(), key_hash, position); } - template iterator move_insert_node_type(NodeType& np) + template + iterator move_insert_node_type_equiv(NodeType& np) { iterator result; @@ -4646,7 +4656,7 @@ struct table_equiv : boost::unordered::detail::table std::size_t key_hash = this->hash(k); node_pointer pos = this->find_node(key_hash, k); this->reserve_for_insert(this->size_ + 1); - result = iterator(this->add_node(np.ptr_, key_hash, pos)); + result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos)); np.ptr_ = node_pointer(); } @@ -4654,7 +4664,8 @@ struct table_equiv : boost::unordered::detail::table } template - iterator move_insert_node_type_with_hint(c_iterator hint, NodeType& np) + iterator move_insert_node_type_with_hint_equiv( + c_iterator hint, NodeType& np) { iterator result; @@ -4663,12 +4674,13 @@ struct table_equiv : boost::unordered::detail::table if (hint.node_ && this->key_eq()(k, this->get_key(hint.node_))) { this->reserve_for_insert(this->size_ + 1); - result = iterator(this->add_using_hint(np.ptr_, hint.node_)); + result = + iterator(this->add_using_hint_equiv(np.ptr_, hint.node_)); } else { std::size_t key_hash = this->hash(k); node_pointer pos = this->find_node(key_hash, k); this->reserve_for_insert(this->size_ + 1); - result = iterator(this->add_node(np.ptr_, key_hash, pos)); + result = iterator(this->add_node_equiv(np.ptr_, key_hash, pos)); } np.ptr_ = node_pointer(); } @@ -4682,7 +4694,7 @@ struct table_equiv : boost::unordered::detail::table // if hash function throws, or inserting > 1 element, basic exception // safety. Strong otherwise template - void insert_range(I i, I j, + void insert_range_equiv(I i, I j, typename boost::unordered::detail::enable_if_forward::type = 0) { @@ -4691,14 +4703,14 @@ struct table_equiv : boost::unordered::detail::table std::size_t distance = static_cast(std::distance(i, j)); if (distance == 1) { - emplace_impl(boost::unordered::detail::func::construct_node( + emplace_equiv(boost::unordered::detail::func::construct_node( this->node_alloc(), *i)); } else { // Only require basic exception safety here this->reserve_for_insert(this->size_ + distance); for (; i != j; ++i) { - emplace_impl_no_rehash( + emplace_no_rehash_equiv( boost::unordered::detail::func::construct_node( this->node_alloc(), *i)); } @@ -4706,12 +4718,12 @@ struct table_equiv : boost::unordered::detail::table } template - void insert_range(I i, I j, + void insert_range_equiv(I i, I j, typename boost::unordered::detail::disable_if_forward::type = 0) { for (; i != j; ++i) { - emplace_impl(boost::unordered::detail::func::construct_node( + emplace_equiv(boost::unordered::detail::func::construct_node( this->node_alloc(), *i)); } } @@ -4719,7 +4731,7 @@ struct table_equiv : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // Extract - inline node_pointer extract_by_iterator(c_iterator n) + inline node_pointer extract_by_iterator_equiv(c_iterator n) { node_pointer i = n.node_; BOOST_ASSERT(i); @@ -4753,7 +4765,7 @@ struct table_equiv : boost::unordered::detail::table // // no throw - std::size_t erase_key(const_key_type& k) + std::size_t erase_key_equiv(const_key_type& k) { if (!this->size_) return 0; @@ -4772,7 +4784,7 @@ struct table_equiv : boost::unordered::detail::table return deleted_count; } - link_pointer erase_nodes(node_pointer i, node_pointer j) + link_pointer erase_nodes_equiv(node_pointer i, node_pointer j) { std::size_t bucket_index = this->hash_to_bucket(i->hash_); @@ -4811,34 +4823,36 @@ struct table_equiv : boost::unordered::detail::table for (node_pointer n = src.begin(); n;) { std::size_t key_hash = n->hash_; node_pointer group_end(node_algo::next_group(n, this)); - node_pointer pos = - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), n->value()), - key_hash, node_pointer()); + node_pointer pos = this->add_node_equiv( + boost::unordered::detail::func::construct_node( + this->node_alloc(), n->value()), + key_hash, node_pointer()); for (n = node_algo::next_node(n); n != group_end; n = node_algo::next_node(n)) { - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), n->value()), + this->add_node_equiv( + boost::unordered::detail::func::construct_node( + this->node_alloc(), n->value()), key_hash, pos); } } } - void move_buckets(table const& src) + void move_buckets_equiv(table const& src) { this->create_buckets(this->bucket_count_); for (node_pointer n = src.begin(); n;) { std::size_t key_hash = n->hash_; node_pointer group_end(node_algo::next_group(n, this)); - node_pointer pos = - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), boost::move(n->value())), - key_hash, node_pointer()); + node_pointer pos = this->add_node_equiv( + boost::unordered::detail::func::construct_node( + this->node_alloc(), boost::move(n->value())), + key_hash, node_pointer()); for (n = node_algo::next_node(n); n != group_end; n = node_algo::next_node(n)) { - this->add_node(boost::unordered::detail::func::construct_node( - this->node_alloc(), boost::move(n->value())), + this->add_node_equiv( + boost::unordered::detail::func::construct_node( + this->node_alloc(), boost::move(n->value())), key_hash, pos); } } @@ -4850,11 +4864,11 @@ struct table_equiv : boost::unordered::detail::table for (node_pointer n = src.begin(); n;) { std::size_t key_hash = n->hash_; node_pointer group_end(node_algo::next_group(n, this)); - node_pointer pos = this->add_node( + node_pointer pos = this->add_node_equiv( holder.copy_of(n->value()), key_hash, node_pointer()); for (n = node_algo::next_node(n); n != group_end; n = node_algo::next_node(n)) { - this->add_node(holder.copy_of(n->value()), key_hash, pos); + this->add_node_equiv(holder.copy_of(n->value()), key_hash, pos); } } } @@ -4865,11 +4879,12 @@ struct table_equiv : boost::unordered::detail::table for (node_pointer n = src.begin(); n;) { std::size_t key_hash = n->hash_; node_pointer group_end(node_algo::next_group(n, this)); - node_pointer pos = this->add_node( + node_pointer pos = this->add_node_equiv( holder.move_copy_of(n->value()), key_hash, node_pointer()); for (n = node_algo::next_node(n); n != group_end; n = node_algo::next_node(n)) { - this->add_node(holder.move_copy_of(n->value()), key_hash, pos); + this->add_node_equiv( + holder.move_copy_of(n->value()), key_hash, pos); } } } diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index a55e2b5c..85f1c134 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -222,7 +222,7 @@ template class unordered_map template std::pair emplace(BOOST_FWD_REF(Args)... args) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract(boost::forward(args)...), boost::forward(args)...); } @@ -248,7 +248,7 @@ template class unordered_map template std::pair emplace(BOOST_FWD_REF(A0) a0) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract(boost::forward(a0)), boost::unordered::detail::create_emplace_args( boost::forward(a0))); @@ -258,7 +258,7 @@ template class unordered_map std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -269,7 +269,7 @@ template class unordered_map std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -284,7 +284,7 @@ template class unordered_map template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { - return table_.emplace_hint_impl(hint, + return table_.emplace_hint_unique(hint, table::extractor::extract(boost::forward(args)...), boost::forward(args)...); } @@ -306,17 +306,17 @@ template class unordered_map template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { - return table_.emplace_hint_impl(hint, + return table_.emplace_hint_unique(hint, table::extractor::extract(boost::forward(a0)), boost::unordered::detail::create_emplace_args( - boost::forward(a0))); + boost::forward(a0))); } template iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.emplace_hint_impl( + return table_.emplace_hint_unique( hint, table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -327,7 +327,7 @@ template class unordered_map iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.emplace_hint_impl( + return table_.emplace_hint_unique( hint, table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -344,7 +344,7 @@ template class unordered_map std::pair emplace( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.emplace_impl( \ + return table_.emplace_unique( \ table::extractor::extract( \ boost::forward(a0), boost::forward(a1)), \ boost::unordered::detail::create_emplace_args( \ @@ -355,7 +355,7 @@ template class unordered_map iterator emplace_hint(const_iterator hint, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.emplace_hint_impl( \ + return table_.emplace_hint_unique( \ hint, table::extractor::extract( \ boost::forward(a0), boost::forward(a1)), \ boost::unordered::detail::create_emplace_args( \ @@ -424,7 +424,7 @@ template class unordered_map node_type extract(const_iterator position) { return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); + table_.extract_by_iterator_unique(position), table_.node_alloc()); } node_type extract(const key_type& k) @@ -435,13 +435,13 @@ template class unordered_map insert_return_type insert(BOOST_RV_REF(node_type) np) { insert_return_type result; - table_.move_insert_node_type(np, result); + table_.move_insert_node_type_unique(np, result); return boost::move(result); } iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type_with_hint(hint, np); + return table_.move_insert_node_type_with_hint_unique(hint, np); } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -459,14 +459,14 @@ template class unordered_map std::pair try_emplace( key_type const& k, BOOST_FWD_REF(Args)... args) { - return table_.try_emplace_impl(k, boost::forward(args)...); + return table_.try_emplace_unique(k, boost::forward(args)...); } template iterator try_emplace( const_iterator hint, key_type const& k, BOOST_FWD_REF(Args)... args) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, k, boost::forward(args)...); } @@ -474,7 +474,7 @@ template class unordered_map std::pair try_emplace( BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( boost::move(k), boost::forward(args)...); } @@ -482,7 +482,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(Args)... args) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, boost::move(k), boost::forward(args)...); } @@ -491,20 +491,20 @@ template class unordered_map template std::pair try_emplace(BOOST_FWD_REF(Key) k) { - return table_.try_emplace_impl(boost::forward(k)); + return table_.try_emplace_unique(boost::forward(k)); } template iterator try_emplace(const_iterator hint, BOOST_FWD_REF(Key) k) { - return table_.try_emplace_hint_impl(hint, boost::forward(k)); + return table_.try_emplace_hint_unique(hint, boost::forward(k)); } template std::pair try_emplace( key_type const& k, BOOST_FWD_REF(A0) a0) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( k, boost::unordered::detail::create_emplace_args( boost::forward(a0))); } @@ -513,7 +513,7 @@ template class unordered_map iterator try_emplace( const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, k, boost::unordered::detail::create_emplace_args( boost::forward(a0))); } @@ -522,7 +522,7 @@ template class unordered_map std::pair try_emplace( BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) { - return table_.try_emplace_impl( + return table_.try_emplace_hint_unique( boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0))); } @@ -531,7 +531,7 @@ template class unordered_map iterator try_emplace( const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0))); } @@ -540,7 +540,7 @@ template class unordered_map std::pair try_emplace( key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( k, boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1))); } @@ -549,7 +549,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, k, boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1))); } @@ -558,7 +558,7 @@ template class unordered_map std::pair try_emplace( BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1))); @@ -568,7 +568,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1))); @@ -578,7 +578,7 @@ template class unordered_map std::pair try_emplace(key_type const& k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( k, boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1), boost::forward(a2))); @@ -589,7 +589,7 @@ template class unordered_map BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { return table_ - .try_emplace_impl_( + .try_emplace_unique( hint, k, boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1), boost::forward(a2))) @@ -600,7 +600,7 @@ template class unordered_map std::pair try_emplace(BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.try_emplace_impl( + return table_.try_emplace_unique( boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1), boost::forward(a2))); @@ -610,7 +610,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.try_emplace_hint_impl( + return table_.try_emplace_hint_unique( hint, boost::move(k), boost::unordered::detail::create_emplace_args( boost::forward(a0), boost::forward(a1), @@ -623,7 +623,7 @@ template class unordered_map std::pair try_emplace( \ key_type const& k, BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.try_emplace_impl( \ + return table_.try_emplace_unique( \ k, boost::unordered::detail::create_emplace_args( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_CALL_FORWARD, a))); \ } \ @@ -632,7 +632,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, key_type const& k, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.try_emplace_hint_impl(hint, k, \ + return table_.try_emplace_hint_unique(hint, k, \ boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ n, BOOST_UNORDERED_CALL_FORWARD, a))); \ } \ @@ -641,7 +641,7 @@ template class unordered_map std::pair try_emplace(BOOST_RV_REF(key_type) k, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.try_emplace_impl(boost::move(k), \ + return table_.try_emplace_unique(boost::move(k), \ boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ n, BOOST_UNORDERED_CALL_FORWARD, a))); \ } \ @@ -650,7 +650,7 @@ template class unordered_map iterator try_emplace(const_iterator hint, BOOST_RV_REF(key_type) k, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.try_emplace_hint_impl(hint, boost::move(k), \ + return table_.try_emplace_hint_unique(hint, boost::move(k), \ boost::unordered::detail::create_emplace_args(BOOST_PP_ENUM_##z( \ n, BOOST_UNORDERED_CALL_FORWARD, a))); \ } @@ -666,14 +666,14 @@ template class unordered_map std::pair insert_or_assign( key_type const& k, BOOST_FWD_REF(M) obj) { - return table_.insert_or_assign_impl(k, boost::forward(obj)); + return table_.insert_or_assign_unique(k, boost::forward(obj)); } template std::pair insert_or_assign( BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) { - return table_.insert_or_assign_impl( + return table_.insert_or_assign_unique( boost::move(k), boost::forward(obj)); } @@ -681,7 +681,7 @@ template class unordered_map iterator insert_or_assign( const_iterator, key_type const& k, BOOST_FWD_REF(M) obj) { - return table_.insert_or_assign_impl(k, boost::forward(obj)).first; + return table_.insert_or_assign_unique(k, boost::forward(obj)).first; } template @@ -689,7 +689,7 @@ template class unordered_map const_iterator, BOOST_RV_REF(key_type) k, BOOST_FWD_REF(M) obj) { return table_ - .insert_or_assign_impl(boost::move(k), boost::forward(obj)) + .insert_or_assign_unique(boost::move(k), boost::forward(obj)) .first; } @@ -1004,7 +1004,7 @@ template class unordered_multimap template iterator emplace(BOOST_FWD_REF(Args)... args) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::forward(args)...))); } @@ -1028,7 +1028,7 @@ template class unordered_multimap template iterator emplace(BOOST_FWD_REF(A0) a0) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1038,7 +1038,7 @@ template class unordered_multimap template iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1049,7 +1049,7 @@ template class unordered_multimap iterator emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1064,7 +1064,7 @@ template class unordered_multimap template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::forward(args)...))); } @@ -1086,7 +1086,7 @@ template class unordered_multimap template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1097,7 +1097,7 @@ template class unordered_multimap iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1108,7 +1108,7 @@ template class unordered_multimap iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -1124,7 +1124,7 @@ template class unordered_multimap template \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return iterator(table_.emplace_impl( \ + return iterator(table_.emplace_equiv( \ boost::unordered::detail::func::construct_node_from_args( \ table_.node_alloc(), \ boost::unordered::detail::create_emplace_args( \ @@ -1135,7 +1135,7 @@ template class unordered_multimap iterator emplace_hint(const_iterator hint, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return iterator(table_.emplace_hint_impl( \ + return iterator(table_.emplace_hint_equiv( \ hint, \ boost::unordered::detail::func::construct_node_from_args( \ table_.node_alloc(), \ @@ -1202,7 +1202,7 @@ template class unordered_multimap node_type extract(const_iterator position) { return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); + table_.extract_by_iterator_equiv(position), table_.node_alloc()); } node_type extract(const key_type& k) @@ -1212,12 +1212,12 @@ template class unordered_multimap iterator insert(BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type(np); + return table_.move_insert_node_type_equiv(np); } iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type_with_hint(hint, np); + return table_.move_insert_node_type_with_hint_equiv(hint, np); } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1515,7 +1515,7 @@ template void unordered_map::insert(InputIt first, InputIt last) { if (first != last) { - table_.insert_range_impl( + table_.insert_range_unique( table::extractor::extract(*first), first, last); } } @@ -1536,7 +1536,7 @@ unordered_map::erase(iterator position) node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_unique(node, next); return iterator(next); } @@ -1547,7 +1547,7 @@ unordered_map::erase(const_iterator position) node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_unique(node, next); return iterator(next); } @@ -1555,7 +1555,7 @@ template typename unordered_map::size_type unordered_map::erase(const key_type& k) { - return table_.erase_key(k); + return table_.erase_key_unique(k); } template @@ -1565,7 +1565,7 @@ unordered_map::erase(const_iterator first, const_iterator last) node_pointer last_node = table::get_node(last); if (first == last) return iterator(last_node); - table_.erase_nodes(table::get_node(first), last_node); + table_.erase_nodes_unique(table::get_node(first), last_node); return iterator(last_node); } @@ -1593,7 +1593,7 @@ template void unordered_map::merge( boost::unordered_map& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1602,7 +1602,7 @@ template void unordered_map::merge( boost::unordered_map&& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #endif @@ -1612,7 +1612,7 @@ template void unordered_map::merge( boost::unordered_multimap& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1621,7 +1621,7 @@ template void unordered_map::merge( boost::unordered_multimap&& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #endif #endif @@ -1709,14 +1709,14 @@ template typename unordered_map::mapped_type& unordered_map::operator[](const key_type& k) { - return table_.try_emplace_impl(k).first->second; + return table_.try_emplace_unique(k).first->second; } template typename unordered_map::mapped_type& unordered_map::operator[](BOOST_RV_REF(key_type) k) { - return table_.try_emplace_impl(boost::move(k)).first->second; + return table_.try_emplace_unique(boost::move(k)).first->second; } template @@ -1793,7 +1793,7 @@ inline bool operator==(unordered_map const& m1, unordered_map x; }; #endif - return m1.table_.equals(m2.table_); + return m1.table_.equals_unique(m2.table_); } template @@ -1806,7 +1806,7 @@ inline bool operator!=(unordered_map const& m1, unordered_map x; }; #endif - return !m1.table_.equals(m2.table_); + return !m1.table_.equals_unique(m2.table_); } template @@ -1990,7 +1990,7 @@ template template void unordered_multimap::insert(InputIt first, InputIt last) { - table_.insert_range(first, last); + table_.insert_range_equiv(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -2009,7 +2009,7 @@ unordered_multimap::erase(iterator position) node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_equiv(node, next); return iterator(next); } @@ -2020,7 +2020,7 @@ unordered_multimap::erase(const_iterator position) node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_equiv(node, next); return iterator(next); } @@ -2028,7 +2028,7 @@ template typename unordered_multimap::size_type unordered_multimap::erase(const key_type& k) { - return table_.erase_key(k); + return table_.erase_key_equiv(k); } template @@ -2039,7 +2039,7 @@ unordered_multimap::erase( node_pointer last_node = table::get_node(last); if (first == last) return iterator(last_node); - table_.erase_nodes(table::get_node(first), last_node); + table_.erase_nodes_equiv(table::get_node(first), last_node); return iterator(last_node); } @@ -2234,7 +2234,7 @@ inline bool operator==(unordered_multimap const& m1, unordered_multimap x; }; #endif - return m1.table_.equals(m2.table_); + return m1.table_.equals_equiv(m2.table_); } template @@ -2247,7 +2247,7 @@ inline bool operator!=(unordered_multimap const& m1, unordered_multimap x; }; #endif - return !m1.table_.equals(m2.table_); + return !m1.table_.equals_equiv(m2.table_); } template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 7bb86954..f6165b10 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -220,7 +220,7 @@ template class unordered_set template std::pair emplace(BOOST_FWD_REF(Args)... args) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract(boost::forward(args)...), boost::forward(args)...); } @@ -246,7 +246,7 @@ template class unordered_set template std::pair emplace(BOOST_FWD_REF(A0) a0) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract(boost::forward(a0)), boost::unordered::detail::create_emplace_args( boost::forward(a0))); @@ -256,7 +256,7 @@ template class unordered_set std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -267,7 +267,7 @@ template class unordered_set std::pair emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.emplace_impl( + return table_.emplace_unique( table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -282,7 +282,7 @@ template class unordered_set template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { - return table_.emplace_hint_impl(hint, + return table_.emplace_hint_unique(hint, table::extractor::extract(boost::forward(args)...), boost::forward(args)...); } @@ -304,17 +304,17 @@ template class unordered_set template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { - return table_.emplace_hint_impl(hint, + return table_.emplace_hint_unique(hint, table::extractor::extract(boost::forward(a0)), boost::unordered::detail::create_emplace_args( - boost::forward(a0))); + boost::forward(a0))); } template iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return table_.emplace_hint_impl( + return table_.emplace_hint_unique( hint, table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -325,7 +325,7 @@ template class unordered_set iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return table_.emplace_hint_impl( + return table_.emplace_hint_unique( hint, table::extractor::extract( boost::forward(a0), boost::forward(a1)), boost::unordered::detail::create_emplace_args( @@ -342,7 +342,7 @@ template class unordered_set std::pair emplace( \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.emplace_impl( \ + return table_.emplace_unique( \ table::extractor::extract( \ boost::forward(a0), boost::forward(a1)), \ boost::unordered::detail::create_emplace_args( \ @@ -353,7 +353,7 @@ template class unordered_set iterator emplace_hint(const_iterator hint, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return table_.emplace_hint_impl( \ + return table_.emplace_hint_unique( \ hint, table::extractor::extract( \ boost::forward(a0), boost::forward(a1)), \ boost::unordered::detail::create_emplace_args( \ @@ -404,7 +404,7 @@ template class unordered_set node_type extract(const_iterator position) { return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); + table_.extract_by_iterator_unique(position), table_.node_alloc()); } node_type extract(const key_type& k) @@ -415,13 +415,13 @@ template class unordered_set insert_return_type insert(BOOST_RV_REF(node_type) np) { insert_return_type result; - table_.move_insert_node_type(np, result); + table_.move_insert_node_type_unique(np, result); return boost::move(result); } iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type_with_hint(hint, np); + return table_.move_insert_node_type_with_hint_unique(hint, np); } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -730,7 +730,7 @@ template class unordered_multiset template iterator emplace(BOOST_FWD_REF(Args)... args) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::forward(args)...))); } @@ -754,7 +754,7 @@ template class unordered_multiset template iterator emplace(BOOST_FWD_REF(A0) a0) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -764,7 +764,7 @@ template class unordered_multiset template iterator emplace(BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -775,7 +775,7 @@ template class unordered_multiset iterator emplace( BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return iterator(table_.emplace_impl( + return iterator(table_.emplace_equiv( boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -790,7 +790,7 @@ template class unordered_multiset template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(Args)... args) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::forward(args)...))); } @@ -812,7 +812,7 @@ template class unordered_multiset template iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -823,7 +823,7 @@ template class unordered_multiset iterator emplace_hint( const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -834,7 +834,7 @@ template class unordered_multiset iterator emplace_hint(const_iterator hint, BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { - return iterator(table_.emplace_hint_impl( + return iterator(table_.emplace_hint_equiv( hint, boost::unordered::detail::func::construct_node_from_args( table_.node_alloc(), boost::unordered::detail::create_emplace_args( @@ -850,7 +850,7 @@ template class unordered_multiset template \ iterator emplace(BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return iterator(table_.emplace_impl( \ + return iterator(table_.emplace_equiv( \ boost::unordered::detail::func::construct_node_from_args( \ table_.node_alloc(), \ boost::unordered::detail::create_emplace_args( \ @@ -861,7 +861,7 @@ template class unordered_multiset iterator emplace_hint(const_iterator hint, \ BOOST_PP_ENUM_##z(n, BOOST_UNORDERED_FWD_PARAM, a)) \ { \ - return iterator(table_.emplace_hint_impl( \ + return iterator(table_.emplace_hint_equiv( \ hint, \ boost::unordered::detail::func::construct_node_from_args( \ table_.node_alloc(), \ @@ -910,7 +910,7 @@ template class unordered_multiset node_type extract(const_iterator position) { return node_type( - table_.extract_by_iterator(position), table_.node_alloc()); + table_.extract_by_iterator_equiv(position), table_.node_alloc()); } node_type extract(const key_type& k) @@ -920,12 +920,12 @@ template class unordered_multiset iterator insert(BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type(np); + return table_.move_insert_node_type_equiv(np); } iterator insert(const_iterator hint, BOOST_RV_REF(node_type) np) { - return table_.move_insert_node_type_with_hint(hint, np); + return table_.move_insert_node_type_with_hint_equiv(hint, np); } #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1211,7 +1211,7 @@ template void unordered_set::insert(InputIt first, InputIt last) { if (first != last) { - table_.insert_range_impl( + table_.insert_range_unique( table::extractor::extract(*first), first, last); } } @@ -1231,7 +1231,7 @@ typename unordered_set::iterator unordered_set::erase( node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_unique(node, next); return iterator(next); } @@ -1239,7 +1239,7 @@ template typename unordered_set::size_type unordered_set::erase( const key_type& k) { - return table_.erase_key(k); + return table_.erase_key_unique(k); } template @@ -1249,7 +1249,7 @@ typename unordered_set::iterator unordered_set::erase( node_pointer last_node = table::get_node(last); if (first == last) return iterator(last_node); - table_.erase_nodes(table::get_node(first), last_node); + table_.erase_nodes_unique(table::get_node(first), last_node); return iterator(last_node); } @@ -1293,7 +1293,7 @@ template void unordered_set::merge( boost::unordered_set& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1302,7 +1302,7 @@ template void unordered_set::merge( boost::unordered_set&& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #endif @@ -1312,7 +1312,7 @@ template void unordered_set::merge( boost::unordered_multiset& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) @@ -1321,7 +1321,7 @@ template void unordered_set::merge( boost::unordered_multiset&& source) { - table_.merge_impl(source.table_); + table_.merge_unique(source.table_); } #endif #endif @@ -1408,7 +1408,7 @@ inline bool operator==( unordered_set x; }; #endif - return m1.table_.equals(m2.table_); + return m1.table_.equals_unique(m2.table_); } template @@ -1421,7 +1421,7 @@ inline bool operator!=( unordered_set x; }; #endif - return !m1.table_.equals(m2.table_); + return !m1.table_.equals_unique(m2.table_); } template @@ -1604,7 +1604,7 @@ template template void unordered_multiset::insert(InputIt first, InputIt last) { - table_.insert_range(first, last); + table_.insert_range_equiv(first, last); } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1623,7 +1623,7 @@ unordered_multiset::erase(const_iterator position) node_pointer node = table::get_node(position); BOOST_ASSERT(node); node_pointer next = table::node_algo::next_node(node); - table_.erase_nodes(node, next); + table_.erase_nodes_equiv(node, next); return iterator(next); } @@ -1631,7 +1631,7 @@ template typename unordered_multiset::size_type unordered_multiset::erase(const key_type& k) { - return table_.erase_key(k); + return table_.erase_key_equiv(k); } template @@ -1641,7 +1641,7 @@ unordered_multiset::erase(const_iterator first, const_iterator last) node_pointer last_node = table::get_node(last); if (first == last) return iterator(last_node); - table_.erase_nodes(table::get_node(first), last_node); + table_.erase_nodes_equiv(table::get_node(first), last_node); return iterator(last_node); } @@ -1809,7 +1809,7 @@ inline bool operator==(unordered_multiset const& m1, unordered_multiset x; }; #endif - return m1.table_.equals(m2.table_); + return m1.table_.equals_equiv(m2.table_); } template @@ -1822,7 +1822,7 @@ inline bool operator!=(unordered_multiset const& m1, unordered_multiset x; }; #endif - return !m1.table_.equals(m2.table_); + return !m1.table_.equals_equiv(m2.table_); } template From 84f1ef6d2d76674910e31c9367dcf5b274c82536 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Apr 2017 09:46:05 +0100 Subject: [PATCH 2/4] Move constructor implementation into containers --- .../boost/unordered/detail/implementation.hpp | 30 +------------------ include/boost/unordered/unordered_map.hpp | 26 ++++++++++++++++ include/boost/unordered/unordered_set.hpp | 26 ++++++++++++++++ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index d45a11a4..8e723f13 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -3729,34 +3729,21 @@ struct table_unique : boost::unordered::detail::table : table(x, node_allocator_traits::select_on_container_copy_construction( x.node_alloc())) { - if (x.size_) { - this->copy_buckets(x); - } } table_unique(table_unique const& x, node_allocator const& a) : table(x, a) { - if (x.size_) { - this->copy_buckets(x); - } } table_unique(table_unique& x, boost::unordered::detail::move_tag m) : table(x, m) { - // The move is done in the base class. } table_unique(table_unique& x, node_allocator const& a, boost::unordered::detail::move_tag m) : table(x, a, m) { - if (this->node_alloc() == x.node_alloc()) { - this->move_buckets_from(x); - } else if (x.size_) { - // TODO: Could pick new bucket size? - this->move_buckets(x); - } } // equals @@ -4438,34 +4425,19 @@ struct table_equiv : boost::unordered::detail::table : table(x, node_allocator_traits::select_on_container_copy_construction( x.node_alloc())) { - if (x.size_) { - copy_buckets(x); - } } - table_equiv(table_equiv const& x, node_allocator const& a) : table(x, a) - { - if (x.size_) { - copy_buckets(x); - } - } + table_equiv(table_equiv const& x, node_allocator const& a) : table(x, a) {} table_equiv(table_equiv& x, boost::unordered::detail::move_tag m) : table(x, m) { - // The move is done in the base class. } table_equiv(table_equiv& x, node_allocator const& a, boost::unordered::detail::move_tag m) : table(x, a, m) { - if (this->node_alloc() == x.node_alloc()) { - this->move_buckets_from(x); - } else if (x.size_) { - // TODO: Could pick new bucket size? - this->move_buckets_equiv(x); - } } // Equality diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 85f1c134..4188a594 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -101,6 +101,7 @@ template class unordered_map BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { + // The move is done in table_ } #endif @@ -883,6 +884,7 @@ template class unordered_multimap BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { + // The move is done in table_ } #endif @@ -1378,6 +1380,9 @@ template unordered_map::unordered_map(unordered_map const& other) : table_(other.table_) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1392,6 +1397,9 @@ unordered_map::unordered_map( unordered_map const& other, allocator_type const& a) : table_(other.table_, a) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1399,6 +1407,12 @@ unordered_map::unordered_map( BOOST_RV_REF(unordered_map) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { + if (table_.node_alloc() == other.table_.node_alloc()) { + table_.move_buckets_from(other.table_); + } else if (other.table_.size_) { + // TODO: Could pick new bucket size? + table_.move_buckets(other.table_); + } } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1854,6 +1868,9 @@ unordered_multimap::unordered_multimap( unordered_multimap const& other) : table_(other.table_) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1868,6 +1885,9 @@ unordered_multimap::unordered_multimap( unordered_multimap const& other, allocator_type const& a) : table_(other.table_, a) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1875,6 +1895,12 @@ unordered_multimap::unordered_multimap( BOOST_RV_REF(unordered_multimap) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { + if (table_.node_alloc() == other.table_.node_alloc()) { + table_.move_buckets_from(other.table_); + } else if (other.table_.size()) { + // TODO: Could pick new bucket size? + table_.move_buckets_equiv(other.table_); + } } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index f6165b10..6ef28460 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -99,6 +99,7 @@ template class unordered_set BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { + // The move is done in table_ } #endif @@ -609,6 +610,7 @@ template class unordered_multiset BOOST_NOEXCEPT_IF(table::nothrow_move_constructible) : table_(other.table_, boost::unordered::detail::move_tag()) { + // The move is done in table_ } #endif @@ -1077,6 +1079,9 @@ template unordered_set::unordered_set(unordered_set const& other) : table_(other.table_) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1091,6 +1096,9 @@ unordered_set::unordered_set( unordered_set const& other, allocator_type const& a) : table_(other.table_, a) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1098,6 +1106,12 @@ unordered_set::unordered_set( BOOST_RV_REF(unordered_set) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { + if (table_.node_alloc() == other.table_.node_alloc()) { + table_.move_buckets_from(other.table_); + } else if (other.table_.size_) { + // TODO: Could pick new bucket size? + table_.move_buckets(other.table_); + } } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) @@ -1468,6 +1482,9 @@ unordered_multiset::unordered_multiset( unordered_multiset const& other) : table_(other.table_) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1482,6 +1499,9 @@ unordered_multiset::unordered_multiset( unordered_multiset const& other, allocator_type const& a) : table_(other.table_, a) { + if (other.table_.size_) { + table_.copy_buckets(other.table_); + } } template @@ -1489,6 +1509,12 @@ unordered_multiset::unordered_multiset( BOOST_RV_REF(unordered_multiset) other, allocator_type const& a) : table_(other.table_, a, boost::unordered::detail::move_tag()) { + if (table_.node_alloc() == other.table_.node_alloc()) { + table_.move_buckets_from(other.table_); + } else if (other.table_.size()) { + // TODO: Could pick new bucket size? + table_.move_buckets_equiv(other.table_); + } } #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) From e5181201041564c3de5281c35388fe10a9c921a6 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Apr 2017 09:46:05 +0100 Subject: [PATCH 3/4] Rename some copy/assign/move methods But with a hack so that the static casts will work until there's a better method. --- .../boost/unordered/detail/implementation.hpp | 42 ++++++++++++++++--- include/boost/unordered/unordered_map.hpp | 8 ++-- include/boost/unordered/unordered_set.hpp | 8 ++-- 3 files changed, 44 insertions(+), 14 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 8e723f13..662af550 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -4146,7 +4146,12 @@ struct table_unique : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // fill_buckets_unique - void copy_buckets(table const& src) + BOOST_FORCEINLINE void copy_buckets(table const& src) + { + this->copy_buckets_unique(src); + } + + void copy_buckets_unique(table const& src) { this->create_buckets(this->bucket_count_); @@ -4170,7 +4175,12 @@ struct table_unique : boost::unordered::detail::table } } - void assign_buckets(table const& src) + BOOST_FORCEINLINE void assign_buckets(table const& src) + { + this->assign_buckets_unique(src); + } + + void assign_buckets_unique(table const& src) { node_holder holder(*this); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { @@ -4178,7 +4188,12 @@ struct table_unique : boost::unordered::detail::table } } - void move_assign_buckets(table& src) + BOOST_FORCEINLINE void move_assign_buckets(table const& src) + { + this->move_assign_buckets_unique(src); + } + + void move_assign_buckets_unique(table& src) { node_holder holder(*this); for (node_pointer n = src.begin(); n; n = node_algo::next_node(n)) { @@ -4788,7 +4803,12 @@ struct table_equiv : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // fill_buckets - void copy_buckets(table const& src) + BOOST_FORCEINLINE void copy_buckets(table const& src) + { + this->copy_buckets_equiv(src); + } + + void copy_buckets_equiv(table const& src) { this->create_buckets(this->bucket_count_); @@ -4830,7 +4850,12 @@ struct table_equiv : boost::unordered::detail::table } } - void assign_buckets(table const& src) + BOOST_FORCEINLINE void assign_buckets(table const& src) + { + this->assign_buckets_equiv(src); + } + + void assign_buckets_equiv(table const& src) { node_holder holder(*this); for (node_pointer n = src.begin(); n;) { @@ -4845,7 +4870,12 @@ struct table_equiv : boost::unordered::detail::table } } - void move_assign_buckets(table& src) + BOOST_FORCEINLINE void move_assign_buckets(table const& src) + { + this->move_assign_buckets_equiv(src); + } + + void move_assign_buckets_equiv(table& src) { node_holder holder(*this); for (node_pointer n = src.begin(); n;) { diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 4188a594..7972cc89 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -1381,7 +1381,7 @@ unordered_map::unordered_map(unordered_map const& other) : table_(other.table_) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_unique(other.table_); } } @@ -1398,7 +1398,7 @@ unordered_map::unordered_map( : table_(other.table_, a) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_unique(other.table_); } } @@ -1869,7 +1869,7 @@ unordered_multimap::unordered_multimap( : table_(other.table_) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_equiv(other.table_); } } @@ -1886,7 +1886,7 @@ unordered_multimap::unordered_multimap( : table_(other.table_, a) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_equiv(other.table_); } } diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 6ef28460..273975ab 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -1080,7 +1080,7 @@ unordered_set::unordered_set(unordered_set const& other) : table_(other.table_) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_unique(other.table_); } } @@ -1097,7 +1097,7 @@ unordered_set::unordered_set( : table_(other.table_, a) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_unique(other.table_); } } @@ -1483,7 +1483,7 @@ unordered_multiset::unordered_multiset( : table_(other.table_) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_equiv(other.table_); } } @@ -1500,7 +1500,7 @@ unordered_multiset::unordered_multiset( : table_(other.table_, a) { if (other.table_.size_) { - table_.copy_buckets(other.table_); + table_.copy_buckets_equiv(other.table_); } } From b070bb5e49a30824a39afe5a820ca82084e595e6 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Mon, 24 Apr 2017 09:46:05 +0100 Subject: [PATCH 4/4] Move everything from table_unique/table_equiv into table --- .../boost/unordered/detail/implementation.hpp | 1361 ++++++++--------- include/boost/unordered/detail/map.hpp | 12 +- include/boost/unordered/detail/set.hpp | 12 +- include/boost/unordered/unordered_map.hpp | 15 +- include/boost/unordered/unordered_set.hpp | 15 +- test/unordered/incomplete_test.cpp | 5 + 6 files changed, 663 insertions(+), 757 deletions(-) diff --git a/include/boost/unordered/detail/implementation.hpp b/include/boost/unordered/detail/implementation.hpp index 662af550..25a7e615 100644 --- a/include/boost/unordered/detail/implementation.hpp +++ b/include/boost/unordered/detail/implementation.hpp @@ -185,9 +185,6 @@ template struct table; template struct bucket; struct ptr_bucket; -template struct table_unique; -template struct table_equiv; - template struct unique_node; template struct ptr_node; template struct node_algo; @@ -198,13 +195,21 @@ template struct grouped_node_algo; static const float minimum_max_load_factor = 1e-3f; static const std::size_t default_bucket_count = 11; + struct move_tag { }; + struct empty_emplace { }; +struct no_key +{ + no_key() {} + template no_key(T const&) {} +}; + namespace func { template inline void ignore_unused_variable_warning(T const&) {} } @@ -2041,8 +2046,6 @@ struct iterator : public std::iterator friend struct boost::unordered::iterator_detail::c_iterator; template friend struct boost::unordered::detail::table; - template friend struct boost::unordered::detail::table_unique; - template friend struct boost::unordered::detail::table_equiv; private: #endif @@ -2097,8 +2100,6 @@ struct c_iterator #if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) template friend struct boost::unordered::detail::table; - template friend struct boost::unordered::detail::table_unique; - template friend struct boost::unordered::detail::table_equiv; private: #endif @@ -2694,6 +2695,8 @@ struct table : boost::unordered::detail::functions node_tmp; + typedef std::pair emplace_return; + //////////////////////////////////////////////////////////////////////// // Members @@ -3116,7 +3119,12 @@ struct table : boost::unordered::detail::functions(this)->assign_buckets(x); + + if (Types::is_unique) { + assign_buckets_unique(x); + } else { + assign_buckets_equiv(x); + } } void assign(table const& x, true_type) @@ -3140,7 +3148,11 @@ struct table : boost::unordered::detail::functions(this)->copy_buckets(x); + if (Types::is_unique) { + copy_buckets_unique(x); + } else { + copy_buckets_equiv(x); + } } } } @@ -3194,7 +3206,12 @@ struct table : boost::unordered::detail::functions(this)->move_assign_buckets(x); + + if (Types::is_unique) { + move_assign_buckets_unique(x); + } else { + move_assign_buckets_equiv(x); + } } } @@ -3298,453 +3315,9 @@ struct table : boost::unordered::detail::functions -inline void table::reserve_for_insert(std::size_t size) -{ - if (!buckets_) { - create_buckets((std::max)(bucket_count_, min_buckets_for_size(size))); - } else if (size > max_load_) { - std::size_t num_buckets = - min_buckets_for_size((std::max)(size, size_ + (size_ >> 1))); - - if (num_buckets != bucket_count_) - this->rehash_impl(num_buckets); - } -} - -// if hash function throws, basic exception safety -// strong otherwise. - -template -inline void table::rehash(std::size_t min_buckets) -{ - using namespace std; - - if (!size_) { - delete_buckets(); - bucket_count_ = policy::new_bucket_count(min_buckets); - } else { - min_buckets = policy::new_bucket_count((std::max)(min_buckets, - boost::unordered::detail::double_to_size( - floor(static_cast(size_) / static_cast(mlf_))) + - 1)); - - if (min_buckets != bucket_count_) - this->rehash_impl(min_buckets); - } -} - -template -inline void table::rehash_impl(std::size_t num_buckets) -{ - BOOST_ASSERT(this->buckets_); - - this->create_buckets(num_buckets); - link_pointer prev = this->get_previous_start(); - while (prev->next_) { - node_pointer group_last = node_algo::last_for_rehash(prev); - bucket_pointer b = - this->get_bucket(this->hash_to_bucket(group_last->hash_)); - if (!b->next_) { - b->next_ = prev; - prev = group_last; - } else { - link_pointer next = group_last->next_; - group_last->next_ = b->next_->next_; - b->next_->next_ = prev->next_; - prev->next_ = next; - } - } -} - -#if defined(BOOST_MSVC) -#pragma warning(pop) -#endif - -//////////////////////////////////////////////////////////////////////// -// key extractors -// -// no throw -// -// 'extract_key' is called with the emplace parameters to return a -// key if available or 'no_key' is one isn't and will need to be -// constructed. This could be done by overloading the emplace implementation -// for the different cases, but that's a bit tricky on compilers without -// variadic templates. - -struct no_key -{ - no_key() {} - template no_key(T const&) {} -}; - -template struct is_key -{ - template static choice1::type test(T2 const&); - static choice2::type test(Key const&); - - enum - { - value = sizeof(test(boost::unordered::detail::make())) == - sizeof(choice2::type) - }; - - typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE - then::type type; -}; - -template struct set_extractor -{ - typedef ValueType value_type; - typedef ValueType key_type; - - static key_type const& extract(value_type const& v) { return v; } - - static no_key extract() { return no_key(); } - - template static no_key extract(Arg const&) { return no_key(); } - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - static no_key extract(Arg1 const&, Arg2 const&, Args const&...) - { - return no_key(); - } -#else - template - static no_key extract(Arg1 const&, Arg2 const&) - { - return no_key(); - } -#endif -}; - -template struct map_extractor -{ - typedef ValueType value_type; - typedef typename boost::remove_const::first_type>::type key_type; - - static key_type const& extract(value_type const& v) { return v.first; } - - template - static key_type const& extract(std::pair const& v) - { - return v.first; - } - - template - static key_type const& extract(std::pair const& v) - { - return v.first; - } - - template - static key_type const& extract(key_type const& k, Arg1 const&) - { - return k; - } - - static no_key extract() { return no_key(); } - - template static no_key extract(Arg const&) { return no_key(); } - - template - static no_key extract(Arg1 const&, Arg2 const&) - { - return no_key(); - } - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - template - static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&, Args const&...) - { - return no_key(); - } -#endif - -#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) - -#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ - template \ - static no_key extract(boost::unordered::piecewise_construct_t, \ - namespace_ tuple<> const&, T2 const&) \ - { \ - return no_key(); \ - } \ - \ - template \ - static typename is_key::type extract( \ - boost::unordered::piecewise_construct_t, namespace_ tuple const& k, \ - T2 const&) \ - { \ - return typename is_key::type(namespace_ get<0>(k)); \ - } - -#else - -#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ - static no_key extract( \ - boost::unordered::piecewise_construct_t, namespace_ tuple<> const&) \ - { \ - return no_key(); \ - } \ - \ - template \ - static typename is_key::type extract( \ - boost::unordered::piecewise_construct_t, namespace_ tuple const& k) \ - { \ - return typename is_key::type(namespace_ get<0>(k)); \ - } - -#endif - - BOOST_UNORDERED_KEY_FROM_TUPLE(boost::) - -#if BOOST_UNORDERED_TUPLE_ARGS - BOOST_UNORDERED_KEY_FROM_TUPLE(std::) -#endif -}; - -//////////////////////////////////////////////////////////////////////// -// Unique nodes - -template -struct unique_node : boost::unordered::detail::value_base -{ - typedef typename ::boost::unordered::detail::rebind_wrap >::type allocator; - typedef typename ::boost::unordered::detail::allocator_traits< - allocator>::pointer node_pointer; - typedef node_pointer link_pointer; - typedef typename ::boost::unordered::detail::rebind_wrap >::type bucket_allocator; - typedef typename ::boost::unordered::detail::allocator_traits< - bucket_allocator>::pointer bucket_pointer; - - link_pointer next_; - std::size_t hash_; - - unique_node() : next_(), hash_(0) {} - - void init(node_pointer) {} - - private: - unique_node& operator=(unique_node const&); -}; - -template struct ptr_node : boost::unordered::detail::ptr_bucket -{ - typedef T value_type; - typedef boost::unordered::detail::ptr_bucket bucket_base; - typedef ptr_node* node_pointer; - typedef ptr_bucket* link_pointer; - typedef ptr_bucket* bucket_pointer; - - std::size_t hash_; - boost::unordered::detail::value_base value_base_; - - ptr_node() : bucket_base(), hash_(0) {} - - void init(node_pointer) {} - - void* address() { return value_base_.address(); } - value_type& value() { return value_base_.value(); } - value_type* value_ptr() { return value_base_.value_ptr(); } - - private: - ptr_node& operator=(ptr_node const&); -}; - -template struct node_algo -{ - typedef typename N::node_pointer node_pointer; - typedef typename N::link_pointer link_pointer; - typedef typename N::bucket_pointer bucket_pointer; - - static node_pointer next_node(link_pointer n) - { - return static_cast(n->next_); - } - - static node_pointer next_for_find(node_pointer n) - { - return static_cast(n->next_); - } - - static link_pointer next_for_erase(link_pointer prev) - { - return prev->next_; - } - - // Group together all nodes with equal hash value, this may - // include nodes with different keys, but that's okay because - // they will end up in the same bucket. - static node_pointer last_for_rehash(link_pointer prev) - { - node_pointer n = next_node(prev); - std::size_t hash = n->hash_; - for (;;) { - node_pointer next = next_node(n); - if (!next || next->hash_ != hash) { - return n; - } - n = next; - } - } - - template - static node_pointer next_group(node_pointer n, Table const* t) - { - node_pointer n1 = n; - do { - n1 = next_node(n1); - } while (n1 && t->key_eq()(t->get_key(n), t->get_key(n1))); - return n1; - } - - template - static std::size_t count(node_pointer n, Table const* t) - { - std::size_t x = 0; - node_pointer it = n; - do { - ++x; - it = next_node(it); - } while (it && t->key_eq()(t->get_key(n), t->get_key(it))); - - return x; - } - - // Add node 'n' after 'pos'. - // This results in a different order to the grouped implementation. - static inline void add_to_node(node_pointer n, node_pointer pos) - { - n->next_ = pos->next_; - pos->next_ = n; - } - - static inline node_pointer extract_first_node(link_pointer prev) - { - node_pointer n = next_node(prev); - prev->next_ = n->next_; - return n; - } - - static link_pointer split_groups(node_pointer, node_pointer) - { - return link_pointer(); - } -}; - -// If the allocator uses raw pointers use ptr_node -// Otherwise use node. - -template -struct pick_node2 -{ - typedef boost::unordered::detail::unique_node node; - - typedef typename boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type>::pointer - node_pointer; - - typedef boost::unordered::detail::bucket bucket; - typedef node_pointer link_pointer; -}; - -template -struct pick_node2*, - boost::unordered::detail::ptr_bucket*> -{ - typedef boost::unordered::detail::ptr_node node; - typedef boost::unordered::detail::ptr_bucket bucket; - typedef bucket* link_pointer; -}; - -template struct pick_node -{ - typedef typename boost::remove_const::type nonconst; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap >::type> - tentative_node_traits; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type> - tentative_bucket_traits; - - typedef pick_node2 - pick; - - typedef typename pick::node node; - typedef typename pick::bucket bucket; - typedef typename pick::link_pointer link_pointer; - typedef boost::unordered::detail::node_algo node_algo; -}; - -template -struct table_unique : boost::unordered::detail::table -{ - typedef boost::unordered::detail::table 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; - typedef typename table::node_allocator node_allocator; - typedef typename table::node_allocator_traits node_allocator_traits; - typedef typename table::bucket_pointer bucket_pointer; - typedef typename table::link_pointer link_pointer; - typedef typename table::hasher hasher; - typedef typename table::key_equal key_equal; - typedef typename table::const_key_type const_key_type; - typedef typename table::node_constructor node_constructor; - typedef typename table::node_tmp node_tmp; - typedef typename table::extractor extractor; - typedef typename table::iterator iterator; - typedef typename table::c_iterator c_iterator; - typedef typename table::node_algo node_algo; - - typedef std::pair emplace_return; - - // Constructors - - table_unique(std::size_t n, hasher const& hf, key_equal const& eq, - node_allocator const& a) - : table(n, hf, eq, a) - { - } - - table_unique(table_unique const& x) - : table(x, node_allocator_traits::select_on_container_copy_construction( - x.node_alloc())) - { - } - - table_unique(table_unique const& x, node_allocator const& a) : table(x, a) - { - } - - table_unique(table_unique& x, boost::unordered::detail::move_tag m) - : table(x, m) - { - } - - table_unique(table_unique& x, node_allocator const& a, - boost::unordered::detail::move_tag m) - : table(x, a, m) - { - } + //////////////////////////////////////////////////////////////////////// + // Unique keys // equals @@ -4146,11 +3719,6 @@ struct table_unique : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // fill_buckets_unique - BOOST_FORCEINLINE void copy_buckets(table const& src) - { - this->copy_buckets_unique(src); - } - void copy_buckets_unique(table const& src) { this->create_buckets(this->bucket_count_); @@ -4163,6 +3731,7 @@ struct table_unique : boost::unordered::detail::table } } + // TODO: Should be move_buckets_uniq void move_buckets(table const& src) { this->create_buckets(this->bucket_count_); @@ -4175,11 +3744,6 @@ struct table_unique : boost::unordered::detail::table } } - BOOST_FORCEINLINE void assign_buckets(table const& src) - { - this->assign_buckets_unique(src); - } - void assign_buckets_unique(table const& src) { node_holder holder(*this); @@ -4188,11 +3752,6 @@ struct table_unique : boost::unordered::detail::table } } - BOOST_FORCEINLINE void move_assign_buckets(table const& src) - { - this->move_assign_buckets_unique(src); - } - void move_assign_buckets_unique(table& src) { node_holder holder(*this); @@ -4200,260 +3759,9 @@ struct table_unique : boost::unordered::detail::table this->add_node_unique(holder.move_copy_of(n->value()), n->hash_); } } -}; -//////////////////////////////////////////////////////////////////////// -// Grouped nodes - -template -struct grouped_node : boost::unordered::detail::value_base -{ - typedef typename ::boost::unordered::detail::rebind_wrap >::type allocator; - typedef typename ::boost::unordered::detail::allocator_traits< - allocator>::pointer node_pointer; - typedef node_pointer link_pointer; - typedef typename ::boost::unordered::detail::rebind_wrap >::type bucket_allocator; - typedef typename ::boost::unordered::detail::allocator_traits< - bucket_allocator>::pointer bucket_pointer; - - link_pointer next_; - node_pointer group_prev_; - std::size_t hash_; - - grouped_node() : next_(), group_prev_(), hash_(0) {} - - void init(node_pointer self) { group_prev_ = self; } - - private: - grouped_node& operator=(grouped_node const&); -}; - -template -struct grouped_ptr_node : boost::unordered::detail::ptr_bucket -{ - typedef T value_type; - typedef boost::unordered::detail::ptr_bucket bucket_base; - typedef grouped_ptr_node* node_pointer; - typedef ptr_bucket* link_pointer; - typedef ptr_bucket* bucket_pointer; - - node_pointer group_prev_; - std::size_t hash_; - boost::unordered::detail::value_base value_base_; - - grouped_ptr_node() : bucket_base(), group_prev_(0), hash_(0) {} - - void init(node_pointer self) { group_prev_ = self; } - - void* address() { return value_base_.address(); } - value_type& value() { return value_base_.value(); } - value_type* value_ptr() { return value_base_.value_ptr(); } - - private: - grouped_ptr_node& operator=(grouped_ptr_node const&); -}; - -template struct grouped_node_algo -{ - typedef typename N::node_pointer node_pointer; - typedef typename N::link_pointer link_pointer; - typedef typename N::bucket_pointer bucket_pointer; - - static node_pointer next_node(link_pointer n) - { - return static_cast(n->next_); - } - - static node_pointer next_for_find(node_pointer n) - { - return static_cast(n->group_prev_->next_); - } - - static link_pointer next_for_erase(link_pointer prev) - { - return static_cast(prev->next_)->group_prev_; - } - - static node_pointer last_for_rehash(link_pointer prev) - { - return static_cast(prev->next_)->group_prev_; - } - - // The 'void*' arguments are pointers to the table, which we - // will ignore, but without groups they could be used to - // access the various functions for dealing with values and keys. - static node_pointer next_group(node_pointer n, void const*) - { - return static_cast(n->group_prev_->next_); - } - - static std::size_t count(node_pointer n, void const*) - { - std::size_t x = 0; - node_pointer it = n; - do { - it = it->group_prev_; - ++x; - } while (it != n); - - return x; - } - - // Adds node 'n' to the group containing 'pos'. - // If 'pos' is the first node in group, add to the end of the group, - // otherwise add before 'pos'. Other versions will probably behave - // differently. - static inline void add_to_node(node_pointer n, node_pointer pos) - { - n->next_ = pos->group_prev_->next_; - n->group_prev_ = pos->group_prev_; - pos->group_prev_->next_ = n; - pos->group_prev_ = n; - } - - static inline node_pointer extract_first_node(link_pointer prev) - { - node_pointer n = next_node(prev); - if (n->group_prev_ != n) { - node_pointer next = next_node(n); - next->group_prev_ = n->group_prev_; - n->group_prev_ = n; - } - prev->next_ = n->next_; - return n; - } - - // Split the groups containing 'i' and 'j' so that they can - // be safely erased/extracted. - static link_pointer split_groups(node_pointer i, node_pointer j) - { - node_pointer prev = i->group_prev_; - if (prev->next_ != i) - prev = node_pointer(); - - if (j) { - node_pointer first = j; - while (first != i && first->group_prev_->next_ == first) { - first = first->group_prev_; - } - - boost::swap(first->group_prev_, j->group_prev_); - if (first == i) - return prev; - } - - if (prev) { - node_pointer first = prev; - while (first->group_prev_->next_ == first) { - first = first->group_prev_; - } - boost::swap(first->group_prev_, i->group_prev_); - } - - return prev; - } -}; - -// If the allocator uses raw pointers use grouped_ptr_node -// Otherwise use grouped_node. - -template -struct pick_grouped_node2 -{ - typedef boost::unordered::detail::grouped_node node; - - typedef typename boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type>::pointer - node_pointer; - - typedef boost::unordered::detail::bucket bucket; - typedef node_pointer link_pointer; -}; - -template -struct pick_grouped_node2*, - boost::unordered::detail::ptr_bucket*> -{ - typedef boost::unordered::detail::grouped_ptr_node node; - typedef boost::unordered::detail::ptr_bucket bucket; - typedef bucket* link_pointer; -}; - -template struct pick_grouped_node -{ - typedef typename boost::remove_const::type nonconst; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap >::type> - tentative_node_traits; - - typedef boost::unordered::detail::allocator_traits< - typename boost::unordered::detail::rebind_wrap::type> - tentative_bucket_traits; - - typedef pick_grouped_node2 - pick; - - typedef typename pick::node node; - typedef typename pick::bucket bucket; - typedef typename pick::link_pointer link_pointer; - typedef boost::unordered::detail::grouped_node_algo node_algo; -}; - -template -struct table_equiv : boost::unordered::detail::table -{ - typedef boost::unordered::detail::table table; - typedef typename table::value_type value_type; - typedef typename table::bucket bucket; - typedef typename table::policy policy; - typedef typename table::node_pointer node_pointer; - typedef typename table::node_allocator node_allocator; - typedef typename table::node_allocator_traits node_allocator_traits; - typedef typename table::bucket_pointer bucket_pointer; - typedef typename table::link_pointer link_pointer; - typedef typename table::hasher hasher; - typedef typename table::key_equal key_equal; - typedef typename table::const_key_type const_key_type; - typedef typename table::node_constructor node_constructor; - typedef typename table::node_tmp node_tmp; - typedef typename table::extractor extractor; - typedef typename table::iterator iterator; - typedef typename table::c_iterator c_iterator; - typedef typename table::node_algo node_algo; - - // Constructors - - table_equiv(std::size_t n, hasher const& hf, key_equal const& eq, - node_allocator const& a) - : table(n, hf, eq, a) - { - } - - table_equiv(table_equiv const& x) - : table(x, node_allocator_traits::select_on_container_copy_construction( - x.node_alloc())) - { - } - - table_equiv(table_equiv const& x, node_allocator const& a) : table(x, a) {} - - table_equiv(table_equiv& x, boost::unordered::detail::move_tag m) - : table(x, m) - { - } - - table_equiv(table_equiv& x, node_allocator const& a, - boost::unordered::detail::move_tag m) - : table(x, a, m) - { - } + //////////////////////////////////////////////////////////////////////// + // Equivalent keys // Equality @@ -4803,11 +4111,6 @@ struct table_equiv : boost::unordered::detail::table //////////////////////////////////////////////////////////////////////// // fill_buckets - BOOST_FORCEINLINE void copy_buckets(table const& src) - { - this->copy_buckets_equiv(src); - } - void copy_buckets_equiv(table const& src) { this->create_buckets(this->bucket_count_); @@ -4850,11 +4153,6 @@ struct table_equiv : boost::unordered::detail::table } } - BOOST_FORCEINLINE void assign_buckets(table const& src) - { - this->assign_buckets_equiv(src); - } - void assign_buckets_equiv(table const& src) { node_holder holder(*this); @@ -4870,11 +4168,6 @@ struct table_equiv : boost::unordered::detail::table } } - BOOST_FORCEINLINE void move_assign_buckets(table const& src) - { - this->move_assign_buckets_equiv(src); - } - void move_assign_buckets_equiv(table& src) { node_holder holder(*this); @@ -4891,6 +4184,596 @@ struct table_equiv : boost::unordered::detail::table } } }; + +//////////////////////////////////////////////////////////////////////////// +// Reserve & Rehash + +// basic exception safety +template +inline void table::reserve_for_insert(std::size_t size) +{ + if (!buckets_) { + create_buckets((std::max)(bucket_count_, min_buckets_for_size(size))); + } else if (size > max_load_) { + std::size_t num_buckets = + min_buckets_for_size((std::max)(size, size_ + (size_ >> 1))); + + if (num_buckets != bucket_count_) + this->rehash_impl(num_buckets); + } +} + +// if hash function throws, basic exception safety +// strong otherwise. + +template +inline void table::rehash(std::size_t min_buckets) +{ + using namespace std; + + if (!size_) { + delete_buckets(); + bucket_count_ = policy::new_bucket_count(min_buckets); + } else { + min_buckets = policy::new_bucket_count((std::max)(min_buckets, + boost::unordered::detail::double_to_size( + floor(static_cast(size_) / static_cast(mlf_))) + + 1)); + + if (min_buckets != bucket_count_) + this->rehash_impl(min_buckets); + } +} + +template +inline void table::rehash_impl(std::size_t num_buckets) +{ + BOOST_ASSERT(this->buckets_); + + this->create_buckets(num_buckets); + link_pointer prev = this->get_previous_start(); + while (prev->next_) { + node_pointer group_last = node_algo::last_for_rehash(prev); + bucket_pointer b = + this->get_bucket(this->hash_to_bucket(group_last->hash_)); + if (!b->next_) { + b->next_ = prev; + prev = group_last; + } else { + link_pointer next = group_last->next_; + group_last->next_ = b->next_->next_; + b->next_->next_ = prev->next_; + prev->next_ = next; + } + } +} + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +//////////////////////////////////////////////////////////////////////// +// key extractors +// +// no throw +// +// 'extract_key' is called with the emplace parameters to return a +// key if available or 'no_key' is one isn't and will need to be +// constructed. This could be done by overloading the emplace implementation +// for the different cases, but that's a bit tricky on compilers without +// variadic templates. + +template struct is_key +{ + template static choice1::type test(T2 const&); + static choice2::type test(Key const&); + + enum + { + value = sizeof(test(boost::unordered::detail::make())) == + sizeof(choice2::type) + }; + + typedef typename boost::detail::if_true::BOOST_NESTED_TEMPLATE + then::type type; +}; + +template struct set_extractor +{ + typedef ValueType value_type; + typedef ValueType key_type; + + static key_type const& extract(value_type const& v) { return v; } + + static no_key extract() { return no_key(); } + + template static no_key extract(Arg const&) { return no_key(); } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + static no_key extract(Arg1 const&, Arg2 const&, Args const&...) + { + return no_key(); + } +#else + template + static no_key extract(Arg1 const&, Arg2 const&) + { + return no_key(); + } +#endif +}; + +template struct map_extractor +{ + typedef ValueType value_type; + typedef typename boost::remove_const::first_type>::type key_type; + + static key_type const& extract(value_type const& v) { return v.first; } + + template + static key_type const& extract(std::pair const& v) + { + return v.first; + } + + template + static key_type const& extract(std::pair const& v) + { + return v.first; + } + + template + static key_type const& extract(key_type const& k, Arg1 const&) + { + return k; + } + + static no_key extract() { return no_key(); } + + template static no_key extract(Arg const&) { return no_key(); } + + template + static no_key extract(Arg1 const&, Arg2 const&) + { + return no_key(); + } + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + template + static no_key extract(Arg1 const&, Arg2 const&, Arg3 const&, Args const&...) + { + return no_key(); + } +#endif + +#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) + +#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ + template \ + static no_key extract(boost::unordered::piecewise_construct_t, \ + namespace_ tuple<> const&, T2 const&) \ + { \ + return no_key(); \ + } \ + \ + template \ + static typename is_key::type extract( \ + boost::unordered::piecewise_construct_t, namespace_ tuple const& k, \ + T2 const&) \ + { \ + return typename is_key::type(namespace_ get<0>(k)); \ + } + +#else + +#define BOOST_UNORDERED_KEY_FROM_TUPLE(namespace_) \ + static no_key extract( \ + boost::unordered::piecewise_construct_t, namespace_ tuple<> const&) \ + { \ + return no_key(); \ + } \ + \ + template \ + static typename is_key::type extract( \ + boost::unordered::piecewise_construct_t, namespace_ tuple const& k) \ + { \ + return typename is_key::type(namespace_ get<0>(k)); \ + } + +#endif + + BOOST_UNORDERED_KEY_FROM_TUPLE(boost::) + +#if BOOST_UNORDERED_TUPLE_ARGS + BOOST_UNORDERED_KEY_FROM_TUPLE(std::) +#endif +}; + +//////////////////////////////////////////////////////////////////////// +// Unique nodes + +template +struct unique_node : boost::unordered::detail::value_base +{ + typedef typename ::boost::unordered::detail::rebind_wrap >::type allocator; + typedef typename ::boost::unordered::detail::allocator_traits< + allocator>::pointer node_pointer; + typedef node_pointer link_pointer; + typedef typename ::boost::unordered::detail::rebind_wrap >::type bucket_allocator; + typedef typename ::boost::unordered::detail::allocator_traits< + bucket_allocator>::pointer bucket_pointer; + + link_pointer next_; + std::size_t hash_; + + unique_node() : next_(), hash_(0) {} + + void init(node_pointer) {} + + private: + unique_node& operator=(unique_node const&); +}; + +template struct ptr_node : boost::unordered::detail::ptr_bucket +{ + typedef T value_type; + typedef boost::unordered::detail::ptr_bucket bucket_base; + typedef ptr_node* node_pointer; + typedef ptr_bucket* link_pointer; + typedef ptr_bucket* bucket_pointer; + + std::size_t hash_; + boost::unordered::detail::value_base value_base_; + + ptr_node() : bucket_base(), hash_(0) {} + + void init(node_pointer) {} + + void* address() { return value_base_.address(); } + value_type& value() { return value_base_.value(); } + value_type* value_ptr() { return value_base_.value_ptr(); } + + private: + ptr_node& operator=(ptr_node const&); +}; + +template struct node_algo +{ + typedef typename N::node_pointer node_pointer; + typedef typename N::link_pointer link_pointer; + typedef typename N::bucket_pointer bucket_pointer; + + static node_pointer next_node(link_pointer n) + { + return static_cast(n->next_); + } + + static node_pointer next_for_find(node_pointer n) + { + return static_cast(n->next_); + } + + static link_pointer next_for_erase(link_pointer prev) + { + return prev->next_; + } + + // Group together all nodes with equal hash value, this may + // include nodes with different keys, but that's okay because + // they will end up in the same bucket. + static node_pointer last_for_rehash(link_pointer prev) + { + node_pointer n = next_node(prev); + std::size_t hash = n->hash_; + for (;;) { + node_pointer next = next_node(n); + if (!next || next->hash_ != hash) { + return n; + } + n = next; + } + } + + template + static node_pointer next_group(node_pointer n, Table const* t) + { + node_pointer n1 = n; + do { + n1 = next_node(n1); + } while (n1 && t->key_eq()(t->get_key(n), t->get_key(n1))); + return n1; + } + + template + static std::size_t count(node_pointer n, Table const* t) + { + std::size_t x = 0; + node_pointer it = n; + do { + ++x; + it = next_node(it); + } while (it && t->key_eq()(t->get_key(n), t->get_key(it))); + + return x; + } + + // Add node 'n' after 'pos'. + // This results in a different order to the grouped implementation. + static inline void add_to_node(node_pointer n, node_pointer pos) + { + n->next_ = pos->next_; + pos->next_ = n; + } + + static inline node_pointer extract_first_node(link_pointer prev) + { + node_pointer n = next_node(prev); + prev->next_ = n->next_; + return n; + } + + static link_pointer split_groups(node_pointer, node_pointer) + { + return link_pointer(); + } +}; + +// If the allocator uses raw pointers use ptr_node +// Otherwise use node. + +template +struct pick_node2 +{ + typedef boost::unordered::detail::unique_node node; + + typedef typename boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap::type>::pointer + node_pointer; + + typedef boost::unordered::detail::bucket bucket; + typedef node_pointer link_pointer; +}; + +template +struct pick_node2*, + boost::unordered::detail::ptr_bucket*> +{ + typedef boost::unordered::detail::ptr_node node; + typedef boost::unordered::detail::ptr_bucket bucket; + typedef bucket* link_pointer; +}; + +template struct pick_node +{ + typedef typename boost::remove_const::type nonconst; + + typedef boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap >::type> + tentative_node_traits; + + typedef boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap::type> + tentative_bucket_traits; + + typedef pick_node2 + pick; + + typedef typename pick::node node; + typedef typename pick::bucket bucket; + typedef typename pick::link_pointer link_pointer; + typedef boost::unordered::detail::node_algo node_algo; +}; + +//////////////////////////////////////////////////////////////////////// +// Grouped nodes + +template +struct grouped_node : boost::unordered::detail::value_base +{ + typedef typename ::boost::unordered::detail::rebind_wrap >::type allocator; + typedef typename ::boost::unordered::detail::allocator_traits< + allocator>::pointer node_pointer; + typedef node_pointer link_pointer; + typedef typename ::boost::unordered::detail::rebind_wrap >::type bucket_allocator; + typedef typename ::boost::unordered::detail::allocator_traits< + bucket_allocator>::pointer bucket_pointer; + + link_pointer next_; + node_pointer group_prev_; + std::size_t hash_; + + grouped_node() : next_(), group_prev_(), hash_(0) {} + + void init(node_pointer self) { group_prev_ = self; } + + private: + grouped_node& operator=(grouped_node const&); +}; + +template +struct grouped_ptr_node : boost::unordered::detail::ptr_bucket +{ + typedef T value_type; + typedef boost::unordered::detail::ptr_bucket bucket_base; + typedef grouped_ptr_node* node_pointer; + typedef ptr_bucket* link_pointer; + typedef ptr_bucket* bucket_pointer; + + node_pointer group_prev_; + std::size_t hash_; + boost::unordered::detail::value_base value_base_; + + grouped_ptr_node() : bucket_base(), group_prev_(0), hash_(0) {} + + void init(node_pointer self) { group_prev_ = self; } + + void* address() { return value_base_.address(); } + value_type& value() { return value_base_.value(); } + value_type* value_ptr() { return value_base_.value_ptr(); } + + private: + grouped_ptr_node& operator=(grouped_ptr_node const&); +}; + +template struct grouped_node_algo +{ + typedef typename N::node_pointer node_pointer; + typedef typename N::link_pointer link_pointer; + typedef typename N::bucket_pointer bucket_pointer; + + static node_pointer next_node(link_pointer n) + { + return static_cast(n->next_); + } + + static node_pointer next_for_find(node_pointer n) + { + return static_cast(n->group_prev_->next_); + } + + static link_pointer next_for_erase(link_pointer prev) + { + return static_cast(prev->next_)->group_prev_; + } + + static node_pointer last_for_rehash(link_pointer prev) + { + return static_cast(prev->next_)->group_prev_; + } + + // The 'void*' arguments are pointers to the table, which we + // will ignore, but without groups they could be used to + // access the various functions for dealing with values and keys. + static node_pointer next_group(node_pointer n, void const*) + { + return static_cast(n->group_prev_->next_); + } + + static std::size_t count(node_pointer n, void const*) + { + std::size_t x = 0; + node_pointer it = n; + do { + it = it->group_prev_; + ++x; + } while (it != n); + + return x; + } + + // Adds node 'n' to the group containing 'pos'. + // If 'pos' is the first node in group, add to the end of the group, + // otherwise add before 'pos'. Other versions will probably behave + // differently. + static inline void add_to_node(node_pointer n, node_pointer pos) + { + n->next_ = pos->group_prev_->next_; + n->group_prev_ = pos->group_prev_; + pos->group_prev_->next_ = n; + pos->group_prev_ = n; + } + + static inline node_pointer extract_first_node(link_pointer prev) + { + node_pointer n = next_node(prev); + if (n->group_prev_ != n) { + node_pointer next = next_node(n); + next->group_prev_ = n->group_prev_; + n->group_prev_ = n; + } + prev->next_ = n->next_; + return n; + } + + // Split the groups containing 'i' and 'j' so that they can + // be safely erased/extracted. + static link_pointer split_groups(node_pointer i, node_pointer j) + { + node_pointer prev = i->group_prev_; + if (prev->next_ != i) + prev = node_pointer(); + + if (j) { + node_pointer first = j; + while (first != i && first->group_prev_->next_ == first) { + first = first->group_prev_; + } + + boost::swap(first->group_prev_, j->group_prev_); + if (first == i) + return prev; + } + + if (prev) { + node_pointer first = prev; + while (first->group_prev_->next_ == first) { + first = first->group_prev_; + } + boost::swap(first->group_prev_, i->group_prev_); + } + + return prev; + } +}; + +// If the allocator uses raw pointers use grouped_ptr_node +// Otherwise use grouped_node. + +template +struct pick_grouped_node2 +{ + typedef boost::unordered::detail::grouped_node node; + + typedef typename boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap::type>::pointer + node_pointer; + + typedef boost::unordered::detail::bucket bucket; + typedef node_pointer link_pointer; +}; + +template +struct pick_grouped_node2*, + boost::unordered::detail::ptr_bucket*> +{ + typedef boost::unordered::detail::grouped_ptr_node node; + typedef boost::unordered::detail::ptr_bucket bucket; + typedef bucket* link_pointer; +}; + +template struct pick_grouped_node +{ + typedef typename boost::remove_const::type nonconst; + + typedef boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap >::type> + tentative_node_traits; + + typedef boost::unordered::detail::allocator_traits< + typename boost::unordered::detail::rebind_wrap::type> + tentative_bucket_traits; + + typedef pick_grouped_node2 + pick; + + typedef typename pick::node node; + typedef typename pick::bucket bucket; + typedef typename pick::link_pointer link_pointer; + typedef boost::unordered::detail::grouped_node_algo node_algo; +}; } } } diff --git a/include/boost/unordered/detail/map.hpp b/include/boost/unordered/detail/map.hpp index a8bf9f3a..1d963965 100644 --- a/include/boost/unordered/detail/map.hpp +++ b/include/boost/unordered/detail/map.hpp @@ -29,8 +29,12 @@ template struct map typedef typename pick::link_pointer link_pointer; typedef typename pick::node_algo node_algo; - typedef boost::unordered::detail::table_unique table; + typedef boost::unordered::detail::table table; typedef boost::unordered::detail::map_extractor extractor; + enum + { + is_unique = true + }; typedef typename boost::unordered::detail::pick_policy::type policy; @@ -71,8 +75,12 @@ struct multimap typedef typename pick::link_pointer link_pointer; typedef typename pick::node_algo node_algo; - typedef boost::unordered::detail::table_equiv table; + typedef boost::unordered::detail::table table; typedef boost::unordered::detail::map_extractor extractor; + enum + { + is_unique = false + }; typedef typename boost::unordered::detail::pick_policy::type policy; diff --git a/include/boost/unordered/detail/set.hpp b/include/boost/unordered/detail/set.hpp index 2e7d6ef5..7b9bdca3 100644 --- a/include/boost/unordered/detail/set.hpp +++ b/include/boost/unordered/detail/set.hpp @@ -29,8 +29,12 @@ template struct set typedef typename pick::link_pointer link_pointer; typedef typename pick::node_algo node_algo; - typedef boost::unordered::detail::table_unique table; + typedef boost::unordered::detail::table table; typedef boost::unordered::detail::set_extractor extractor; + enum + { + is_unique = true + }; typedef typename boost::unordered::detail::pick_policy::type policy; @@ -70,8 +74,12 @@ template struct multiset typedef typename pick::link_pointer link_pointer; typedef typename pick::node_algo node_algo; - typedef boost::unordered::detail::table_equiv table; + typedef boost::unordered::detail::table table; typedef boost::unordered::detail::set_extractor extractor; + enum + { + is_unique = false + }; typedef typename boost::unordered::detail::pick_policy::type policy; diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index 7972cc89..57798ca5 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -1378,7 +1378,9 @@ unordered_map::unordered_map(InputIt f, InputIt l, size_type n, template unordered_map::unordered_map(unordered_map const& other) - : table_(other.table_) + : table_(other.table_, + unordered_map::value_allocator_traits:: + select_on_container_copy_construction(other.get_allocator())) { if (other.table_.size_) { table_.copy_buckets_unique(other.table_); @@ -1866,7 +1868,9 @@ unordered_multimap::unordered_multimap(InputIt f, InputIt l, template unordered_multimap::unordered_multimap( unordered_multimap const& other) - : table_(other.table_) + : table_(other.table_, + unordered_multimap::value_allocator_traits:: + select_on_container_copy_construction(other.get_allocator())) { if (other.table_.size_) { table_.copy_buckets_equiv(other.table_); @@ -1897,7 +1901,7 @@ unordered_multimap::unordered_multimap( { if (table_.node_alloc() == other.table_.node_alloc()) { table_.move_buckets_from(other.table_); - } else if (other.table_.size()) { + } else if (other.table_.size_) { // TODO: Could pick new bucket size? table_.move_buckets_equiv(other.table_); } @@ -2294,10 +2298,7 @@ template class node_handle_map { BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_map) - template - friend struct ::boost::unordered::detail::table_unique; - template - friend struct ::boost::unordered::detail::table_equiv; + template friend struct ::boost::unordered::detail::table; template friend class boost::unordered::unordered_map; template diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index 273975ab..36645b99 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -1077,7 +1077,9 @@ unordered_set::unordered_set(InputIt f, InputIt l, size_type n, template unordered_set::unordered_set(unordered_set const& other) - : table_(other.table_) + : table_(other.table_, + unordered_set::value_allocator_traits:: + select_on_container_copy_construction(other.get_allocator())) { if (other.table_.size_) { table_.copy_buckets_unique(other.table_); @@ -1480,7 +1482,9 @@ unordered_multiset::unordered_multiset(InputIt f, InputIt l, template unordered_multiset::unordered_multiset( unordered_multiset const& other) - : table_(other.table_) + : table_(other.table_, + unordered_multiset::value_allocator_traits:: + select_on_container_copy_construction(other.get_allocator())) { if (other.table_.size_) { table_.copy_buckets_equiv(other.table_); @@ -1511,7 +1515,7 @@ unordered_multiset::unordered_multiset( { if (table_.node_alloc() == other.table_.node_alloc()) { table_.move_buckets_from(other.table_); - } else if (other.table_.size()) { + } else if (other.table_.size_) { // TODO: Could pick new bucket size? table_.move_buckets_equiv(other.table_); } @@ -1869,10 +1873,7 @@ template class node_handle_set { BOOST_MOVABLE_BUT_NOT_COPYABLE(node_handle_set) - template - friend struct ::boost::unordered::detail::table_unique; - template - friend struct ::boost::unordered::detail::table_equiv; + template friend struct ::boost::unordered::detail::table; template friend class unordered_set; template diff --git a/test/unordered/incomplete_test.cpp b/test/unordered/incomplete_test.cpp index 8848fe80..860606b3 100644 --- a/test/unordered/incomplete_test.cpp +++ b/test/unordered/incomplete_test.cpp @@ -65,6 +65,11 @@ template struct allocator : std::allocator allocator(const allocator& other) : std::allocator(other) { } + + template + allocator(const std::allocator& other) : std::allocator(other) + { + } }; // Declare some members of a structs.