diff --git a/include/boost/unordered/detail/fwd.hpp b/include/boost/unordered/detail/fwd.hpp index a4ffdb7c..2d18775a 100644 --- a/include/boost/unordered/detail/fwd.hpp +++ b/include/boost/unordered/detail/fwd.hpp @@ -152,76 +152,13 @@ namespace boost { namespace unordered_detail { template class hash_node : public NodeBase, public value_base { + public: typedef ValueType value_type; typedef BOOST_DEDUCED_TYPENAME NodeBase::node_ptr node_ptr; - public: + static value_type& get_value(node_ptr p) { return static_cast(*p).value(); } }; - template - struct hash_structure - { - typedef BOOST_DEDUCED_TYPENAME - G::BOOST_NESTED_TEMPLATE base::type - node_base; - typedef BOOST_DEDUCED_TYPENAME node_base::bucket_allocator bucket_allocator; - typedef BOOST_DEDUCED_TYPENAME node_base::bucket_ptr bucket_ptr; - typedef BOOST_DEDUCED_TYPENAME node_base::node_ptr node_ptr; - - // The actual data structure - - bucket_ptr buckets_; - bucket_ptr cached_begin_bucket_; - std::size_t size_; - std::size_t bucket_count_; - - // Constructor - - hash_structure() : buckets_(), cached_begin_bucket_(), size_() {} - - void swap(hash_structure& other); - - // Buckets - - std::size_t bucket_count() const; - std::size_t bucket_from_hash(std::size_t hashed) const; - bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const; - bucket_ptr buckets_begin() const; - bucket_ptr buckets_end() const; - std::size_t bucket_size(std::size_t index) const; - - // Link a node - - void link_node(node_ptr n, node_ptr position); - void link_node_in_bucket(node_ptr n, bucket_ptr bucket); - void unlink_node(bucket_ptr bucket, node_ptr pos); - void unlink_nodes(bucket_ptr bucket, node_ptr begin, node_ptr end); - void unlink_nodes(bucket_ptr bucket, node_ptr end); - std::size_t unlink_group(node_ptr* pos); - void link_group(node_ptr n, bucket_ptr bucket, std::size_t count); - bucket_ptr get_bucket(std::size_t n) const; - node_ptr bucket_begin(std::size_t n) const; - node_ptr bucket_end(std::size_t) const; - - // recompute_begin_bucket - // - // After an erase cached_begin_bucket_ might be left pointing to - // an empty bucket, so this is called to update it - // - // no throw - - void recompute_begin_bucket(bucket_ptr b); - - // This is called when a range has been erased - // - // no throw - - void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2); - - // no throw - float load_factor() const; - }; - // Iterator Base template @@ -256,22 +193,22 @@ namespace boost { namespace unordered_detail { // methods (other than getters and setters). template - struct hash_table_manager : - hash_structure + struct hash_table_manager { // Types - typedef hash_bucket bucket; - typedef hash_structure structure; - typedef BOOST_DEDUCED_TYPENAME structure::bucket_allocator bucket_allocator; - typedef BOOST_DEDUCED_TYPENAME structure::node_base node_base; - typedef BOOST_DEDUCED_TYPENAME structure::bucket_ptr bucket_ptr; - typedef BOOST_DEDUCED_TYPENAME structure::node_ptr node_ptr; - typedef A value_allocator; typedef BOOST_DEDUCED_TYPENAME A::value_type value_type; + typedef hash_bucket bucket; + typedef BOOST_DEDUCED_TYPENAME G::BOOST_NESTED_TEMPLATE base::type + node_base; typedef hash_node node; + + typedef BOOST_DEDUCED_TYPENAME node::bucket_allocator bucket_allocator; + typedef BOOST_DEDUCED_TYPENAME node::bucket_ptr bucket_ptr; + typedef BOOST_DEDUCED_TYPENAME node::node_ptr node_ptr; + typedef BOOST_DEDUCED_TYPENAME rebind_wrap::type node_allocator; typedef BOOST_DEDUCED_TYPENAME node_allocator::pointer real_node_ptr; @@ -279,6 +216,10 @@ namespace boost { namespace unordered_detail { // Members + bucket_ptr buckets_; + bucket_ptr cached_begin_bucket_; + std::size_t size_; + std::size_t bucket_count_; boost::compressed_pair allocators_; // Data access @@ -306,11 +247,21 @@ namespace boost { namespace unordered_detail { ~hash_table_manager(); // no throw + void swap(hash_table_manager& other); void move(hash_table_manager& other); - // Methods - + // Buckets + void create_buckets(std::size_t bucket_count); + std::size_t bucket_count() const; + std::size_t bucket_from_hash(std::size_t hashed) const; + bucket_ptr bucket_ptr_from_hash(std::size_t hashed) const; + bucket_ptr buckets_begin() const; + bucket_ptr buckets_end() const; + std::size_t bucket_size(std::size_t index) const; + bucket_ptr get_bucket(std::size_t n) const; + node_ptr bucket_begin(std::size_t n) const; + node_ptr bucket_end(std::size_t) const; // Alloc/Dealloc @@ -331,6 +282,24 @@ namespace boost { namespace unordered_detail { iterator_base erase(iterator_base r); std::size_t erase_group(node_ptr* it, bucket_ptr bucket); iterator_base erase_range(iterator_base r1, iterator_base r2); + + // recompute_begin_bucket + // + // After an erase cached_begin_bucket_ might be left pointing to + // an empty bucket, so this is called to update it + // + // no throw + + void recompute_begin_bucket(bucket_ptr b); + + // This is called when a range has been erased + // + // no throw + + void recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2); + + // no throw + float load_factor() const; }; template diff --git a/include/boost/unordered/detail/insert.hpp b/include/boost/unordered/detail/insert.hpp index 211df518..28c27eb4 100644 --- a/include/boost/unordered/detail/insert.hpp +++ b/include/boost/unordered/detail/insert.hpp @@ -70,7 +70,9 @@ namespace boost { namespace unordered_detail { inline node_ptr add_node(node_constructor& a, bucket_ptr bucket) { node_ptr n = a.release(); - this->link_node_in_bucket(n, bucket); + node::add_to_bucket(n, *bucket); + ++this->size_; + if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket; return n; } @@ -328,10 +330,14 @@ namespace boost { namespace unordered_detail { inline node_ptr add_node(node_constructor& a, bucket_ptr bucket, node_ptr pos) { node_ptr n = a.release(); - if(BOOST_UNORDERED_BORLAND_BOOL(pos)) - this->link_node(n, pos); - else - this->link_node_in_bucket(n, bucket); + if(BOOST_UNORDERED_BORLAND_BOOL(pos)) { + node::add_after_node(n, pos); + } + else { + node::add_to_bucket(n, *bucket); + if(bucket < this->cached_begin_bucket_) this->cached_begin_bucket_ = bucket; + } + ++this->size_; return n; } diff --git a/include/boost/unordered/detail/manager.hpp b/include/boost/unordered/detail/manager.hpp index ae69bf1f..5b9d7383 100644 --- a/include/boost/unordered/detail/manager.hpp +++ b/include/boost/unordered/detail/manager.hpp @@ -9,7 +9,7 @@ #include #include -#include +#include namespace boost { namespace unordered_detail { @@ -30,19 +30,19 @@ namespace boost { namespace unordered_detail { template hash_table_manager::hash_table_manager() - : structure(), allocators_() {} + : buckets_(), cached_begin_bucket_(), size_(), allocators_() {} template hash_table_manager::hash_table_manager(value_allocator const& a) - : structure(), allocators_(a,a) {} + : buckets_(), cached_begin_bucket_(), size_(), allocators_(a,a) {} template hash_table_manager::hash_table_manager(hash_table_manager const& h) - : structure(), allocators_(h.allocators_) {} + : buckets_(), cached_begin_bucket_(), size_(), allocators_(h.allocators_) {} template hash_table_manager::hash_table_manager(hash_table_manager& x, move_tag) - : structure(), allocators_(x.allocators_) + : buckets_(), cached_begin_bucket_(), size_(), allocators_(x.allocators_) { this->buckets_ = x.buckets_; this->cached_begin_bucket_ = x.cached_begin_bucket_; @@ -56,7 +56,7 @@ namespace boost { namespace unordered_detail { template hash_table_manager::hash_table_manager(hash_table_manager& x, value_allocator const& a, move_tag) : - structure(), allocators_(a,a) + buckets_(), cached_begin_bucket_(), size_(), allocators_(a,a) { if(this->node_alloc() == x.node_alloc()) { this->buckets_ = x.buckets_; @@ -78,8 +78,9 @@ namespace boost { namespace unordered_detail { // no throw template - void hash_table_manager::move(hash_table_manager& other) + inline void hash_table_manager::move(hash_table_manager& other) { + BOOST_ASSERT(node_alloc() == other.node_alloc()); delete_buckets(); this->buckets_ = other.buckets_; this->cached_begin_bucket_ = other.cached_begin_bucket_; @@ -91,6 +92,131 @@ namespace boost { namespace unordered_detail { other.bucket_count_ = 0; } + template + inline void hash_table_manager::swap(hash_table_manager& other) + { + BOOST_ASSERT(node_alloc() == other.node_alloc()); + std::swap(buckets_, other.buckets_); + std::swap(cached_begin_bucket_, other.cached_begin_bucket_); + std::swap(size_, other.size_); + std::swap(bucket_count_, other.bucket_count_); + } + + // Buckets + + template + inline std::size_t hash_table_manager::bucket_count() const + { + return bucket_count_; + } + + template + inline std::size_t hash_table_manager::bucket_from_hash(std::size_t hashed) const + { + return hashed % bucket_count_; + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::bucket_ptr + hash_table_manager::bucket_ptr_from_hash(std::size_t hashed) const + { + return buckets_ + static_cast( + bucket_from_hash(hashed)); + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::bucket_ptr + hash_table_manager::buckets_begin() const + { + return buckets_; + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::bucket_ptr + hash_table_manager::buckets_end() const + { + return buckets_ + static_cast(bucket_count_); + } + + template + inline std::size_t hash_table_manager::bucket_size(std::size_t index) const + { + bucket_ptr ptr = (buckets_ + static_cast(index))->next_; + std::size_t count = 0; + while(ptr) { + ++count; + ptr = next_node(ptr); + } + return count; + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::bucket_ptr + hash_table_manager::get_bucket(std::size_t n) const + { + return buckets_ + static_cast(n); + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::node_ptr + hash_table_manager::bucket_begin(std::size_t n) const + { + return (buckets_ + static_cast(n))->next_; + } + + template + inline BOOST_DEDUCED_TYPENAME hash_table_manager::node_ptr + hash_table_manager::bucket_end(std::size_t) const + { + return node_ptr(); + } + + // recompute_begin_bucket + // + // After an erase cached_begin_bucket_ might be left pointing to + // an empty bucket, so this is called to update it + // + // no throw + + template + inline void hash_table_manager::recompute_begin_bucket(bucket_ptr b) + { + BOOST_ASSERT(!(b < cached_begin_bucket_)); + + if(b == cached_begin_bucket_) + { + if (size_ != 0) { + while (!cached_begin_bucket_->next_) + ++cached_begin_bucket_; + } else { + cached_begin_bucket_ = buckets_end(); + } + } + } + + // This is called when a range has been erased + // + // no throw + + template + inline void hash_table_manager::recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2) + { + BOOST_ASSERT(!(b1 < cached_begin_bucket_) && !(b2 < b1)); + BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_)); + + if(b1 == cached_begin_bucket_ && !b1->next_) + cached_begin_bucket_ = b2; + } + + // no throw + template + inline float hash_table_manager::load_factor() const + { + BOOST_ASSERT(bucket_count_ != 0); + return static_cast(size_) + / static_cast(bucket_count_); + } + // Construct/destruct template @@ -117,7 +243,7 @@ namespace boost { namespace unordered_detail { } template - void hash_table_manager::destruct_node(node_ptr b) + inline void hash_table_manager::destruct_node(node_ptr b) { node* raw_ptr = static_cast(&*b); BOOST_UNORDERED_DESTRUCT(&raw_ptr->value(), value_type); @@ -129,13 +255,13 @@ namespace boost { namespace unordered_detail { // Delete and clear buckets template - void hash_table_manager::delete_group(node_ptr first_node) + inline void hash_table_manager::delete_group(node_ptr first_node) { delete_nodes(first_node, node::next_group(first_node)); } template - void hash_table_manager::delete_nodes(node_ptr begin, node_ptr end) + inline void hash_table_manager::delete_nodes(node_ptr begin, node_ptr end) { while(begin != end) { node_ptr node = begin; @@ -145,7 +271,7 @@ namespace boost { namespace unordered_detail { } template - void hash_table_manager::delete_to_bucket_end(node_ptr begin) + inline void hash_table_manager::delete_to_bucket_end(node_ptr begin) { while(BOOST_UNORDERED_BORLAND_BOOL(begin)) { node_ptr node = begin; @@ -155,7 +281,7 @@ namespace boost { namespace unordered_detail { } template - void hash_table_manager::clear_bucket(bucket_ptr b) + inline void hash_table_manager::clear_bucket(bucket_ptr b) { node_ptr node_it = b->next_; b->next_ = node_ptr(); @@ -179,7 +305,7 @@ namespace boost { namespace unordered_detail { } template - void hash_table_manager::delete_buckets() + inline void hash_table_manager::delete_buckets() { clear(); @@ -202,7 +328,8 @@ namespace boost { namespace unordered_detail { BOOST_ASSERT(!r.is_end()); iterator_base next = r; next.increment(); - this->unlink_node(r.bucket_, r.node_); + --this->size_; + node::unlink_node(*r.bucket_, r.node_); destruct_node(r.node_); // r has been invalidated but its bucket is still valid this->recompute_begin_bucket(r.bucket_, next.bucket_); @@ -210,14 +337,14 @@ namespace boost { namespace unordered_detail { } template - std::size_t hash_table_manager::erase_group(node_ptr* it, bucket_ptr bucket) + inline std::size_t hash_table_manager::erase_group(node_ptr* it, bucket_ptr bucket) { node_ptr pos = *it; - std::size_t count = this->unlink_group(it); + std::size_t count = node::group_count(*it); + this->size_ -= count; + node::unlink_group(it); delete_group(pos); - this->recompute_begin_bucket(bucket); - return count; } @@ -230,7 +357,8 @@ namespace boost { namespace unordered_detail { BOOST_ASSERT(!r1.is_end()); if (r1.bucket_ == r2.bucket_) { - this->unlink_nodes(r1.bucket_, r1.node_, r2.node_); + this->size_ -= node_count(r1.node_, r2.node_); + node::unlink_nodes(*r1.bucket_, r1.node_, r2.node_); delete_nodes(r1.node_, r2.node_); // No need to call recompute_begin_bucket because @@ -241,7 +369,8 @@ namespace boost { namespace unordered_detail { else { BOOST_ASSERT(r1.bucket_ < r2.bucket_); - this->unlink_nodes(r1.bucket_, r1.node_, node_ptr()); + this->size_ -= node_count(r1.node_, node_ptr()); + node::unlink_nodes(*r1.bucket_, r1.node_, node_ptr()); delete_to_bucket_end(r1.node_); bucket_ptr i = r1.bucket_; @@ -252,7 +381,8 @@ namespace boost { namespace unordered_detail { if(!r2.is_end()) { node_ptr first = r2.bucket_->next_; - this->unlink_nodes(r2.bucket_, r2.node_); + this->size_ -= node_count(r2.bucket_->next_, r2.node_); + node::unlink_nodes(*r2.bucket_, r2.node_); delete_nodes(first, r2.node_); } @@ -265,6 +395,24 @@ namespace boost { namespace unordered_detail { return r2; } + //////////////////////////////////////////////////////////////////////////// + // hash_iterator_base implementation + + template + inline void hash_iterator_base::increment(node_ptr node) { + while(!node) { + ++bucket_; + node = bucket_->next_; + } + + node_ = node; + } + + template + inline void hash_iterator_base::increment() + { + increment(next_node(node_)); + } }} #endif diff --git a/include/boost/unordered/detail/node.hpp b/include/boost/unordered/detail/node.hpp index d6e95a49..90099f46 100644 --- a/include/boost/unordered/detail/node.hpp +++ b/include/boost/unordered/detail/node.hpp @@ -79,13 +79,13 @@ namespace boost { namespace unordered_detail { } template - void ungrouped_node_base::unlink_node(bucket& b, node_ptr node) + inline void ungrouped_node_base::unlink_node(bucket& b, node_ptr node) { unlink_nodes(b, node, next_node(node)); } template - void ungrouped_node_base::unlink_nodes(bucket& b, node_ptr begin, node_ptr end) + inline void ungrouped_node_base::unlink_nodes(bucket& b, node_ptr begin, node_ptr end) { node_ptr* pos = &b.next_; while(*pos != begin) pos = &next_node(*pos); @@ -93,7 +93,7 @@ namespace boost { namespace unordered_detail { } template - void ungrouped_node_base::unlink_nodes(bucket& b, node_ptr end) + inline void ungrouped_node_base::unlink_nodes(bucket& b, node_ptr end) { b.next_ = end; } diff --git a/include/boost/unordered/detail/structure.hpp b/include/boost/unordered/detail/structure.hpp deleted file mode 100644 index d9b5c633..00000000 --- a/include/boost/unordered/detail/structure.hpp +++ /dev/null @@ -1,220 +0,0 @@ - -// Copyright (C) 2003-2004 Jeremy B. Maitin-Shepard. -// Copyright (C) 2005-2009 Daniel James -// Distributed under the Boost Software License, Version 1.0. (See accompanying -// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) - -// This contains the basic data structure, apart from the actual values. There's -// no construction or deconstruction here. So this only depends on the pointer -// type. - -#ifndef BOOST_UNORDERED_DETAIL_STRUCTURE_HPP_INCLUDED -#define BOOST_UNORDERED_DETAIL_STRUCTURE_HPP_INCLUDED - -#include - -namespace boost { namespace unordered_detail { - - //////////////////////////////////////////////////////////////////////////// - // hash_structure implementation - - template - void hash_structure::swap(hash_structure& other) - { - std::swap(buckets_, other.buckets_); - std::swap(cached_begin_bucket_, other.cached_begin_bucket_); - std::swap(size_, other.size_); - std::swap(bucket_count_, other.bucket_count_); - } - - template - std::size_t hash_structure::bucket_count() const - { - return bucket_count_; - } - - template - std::size_t hash_structure::bucket_from_hash(std::size_t hashed) const - { - return hashed % bucket_count_; - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::bucket_ptr - hash_structure::bucket_ptr_from_hash(std::size_t hashed) const - { - return buckets_ + static_cast( - bucket_from_hash(hashed)); - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::bucket_ptr - hash_structure::buckets_begin() const - { - return buckets_; - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::bucket_ptr - hash_structure::buckets_end() const - { - return buckets_ + static_cast(bucket_count_); - } - - template - std::size_t hash_structure::bucket_size(std::size_t index) const - { - bucket_ptr ptr = (buckets_ + static_cast(index))->next_; - std::size_t count = 0; - while(ptr) { - ++count; - ptr = next_node(ptr); - } - return count; - } - - // Link a node - - template - void hash_structure::link_node(node_ptr n, node_ptr position) - { - node_base::add_after_node(n, position); - ++size_; - } - - template - void hash_structure::link_node_in_bucket(node_ptr n, bucket_ptr bucket) - { - node_base::add_to_bucket(n, *bucket); - ++size_; - if(bucket < cached_begin_bucket_) cached_begin_bucket_ = bucket; - } - - template - void hash_structure::unlink_node(bucket_ptr bucket, node_ptr pos) - { - --size_; - node_base::unlink_node(*bucket, pos); - } - - template - void hash_structure::unlink_nodes( - bucket_ptr bucket, node_ptr begin, node_ptr end) - { - size_ -= node_count(begin, end); - node_base::unlink_nodes(*bucket, begin, end); - } - - template - void hash_structure::unlink_nodes(bucket_ptr bucket, node_ptr end) - { - size_ -= node_count(bucket->next_, end); - node_base::unlink_nodes(*bucket, end); - } - - template - std::size_t hash_structure::unlink_group(node_ptr* pos) - { - std::size_t count = node_base::group_count(*pos); - size_ -= count; - node_base::unlink_group(pos); - return count; - } - - template - void hash_structure::link_group( - node_ptr n, bucket_ptr bucket, std::size_t count) - { - node_base::add_group_to_bucket(n, *bucket); - size_ += count; - if(bucket < cached_begin_bucket_) cached_begin_bucket_ = bucket; - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::bucket_ptr - hash_structure::get_bucket(std::size_t n) const - { - return buckets_ + static_cast(n); - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::node_ptr - hash_structure::bucket_begin(std::size_t n) const - { - return (buckets_ + static_cast(n))->next_; - } - - template - BOOST_DEDUCED_TYPENAME hash_structure::node_ptr - hash_structure::bucket_end(std::size_t) const - { - return node_ptr(); - } - - // recompute_begin_bucket - // - // After an erase cached_begin_bucket_ might be left pointing to - // an empty bucket, so this is called to update it - // - // no throw - - template - void hash_structure::recompute_begin_bucket(bucket_ptr b) - { - BOOST_ASSERT(!(b < cached_begin_bucket_)); - - if(b == cached_begin_bucket_) - { - if (size_ != 0) { - while (!cached_begin_bucket_->next_) - ++cached_begin_bucket_; - } else { - cached_begin_bucket_ = buckets_end(); - } - } - } - - // This is called when a range has been erased - // - // no throw - - template - void hash_structure::recompute_begin_bucket(bucket_ptr b1, bucket_ptr b2) - { - BOOST_ASSERT(!(b1 < cached_begin_bucket_) && !(b2 < b1)); - BOOST_ASSERT(BOOST_UNORDERED_BORLAND_BOOL(b2->next_)); - - if(b1 == cached_begin_bucket_ && !b1->next_) - cached_begin_bucket_ = b2; - } - - // no throw - template - inline float hash_structure::load_factor() const - { - BOOST_ASSERT(bucket_count_ != 0); - return static_cast(size_) - / static_cast(bucket_count_); - } - - //////////////////////////////////////////////////////////////////////////// - // hash_iterator_base implementation - - template - inline void hash_iterator_base::increment(node_ptr node) { - while(!node) { - ++bucket_; - node = bucket_->next_; - } - - node_ = node; - } - - template - inline void hash_iterator_base::increment() - { - increment(next_node(node_)); - } -}} - -#endif diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 7c9c61eb..f36e691c 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -327,7 +327,7 @@ namespace boost { namespace unordered_detail { // basic exception safety template - bool hash_table + inline bool hash_table ::reserve(std::size_t n) { bool need_to_reserve = n >= this->max_load_; @@ -339,7 +339,7 @@ namespace boost { namespace unordered_detail { // basic exception safety template - bool hash_table + inline bool hash_table ::reserve_for_insert(std::size_t n) { bool need_to_reserve = n >= this->max_load_; @@ -419,8 +419,12 @@ namespace boost { namespace unordered_detail { hf(extractor::extract(node::get_value(src_bucket->next_)))); node_ptr n = src_bucket->next_; - std::size_t count = this->unlink_group(&src_bucket->next_); - dst.link_group(n, dst_bucket, count); + std::size_t count = node::group_count(src_bucket->next_); + this->size_ -= count; + dst.size_ += count; + node::unlink_group(&src_bucket->next_); + node::add_group_to_bucket(n, *dst_bucket); + if(dst_bucket < dst.cached_begin_bucket_) dst.cached_begin_bucket_ = dst_bucket; } } } @@ -454,11 +458,14 @@ namespace boost { namespace unordered_detail { a.construct(node::get_value(it)); node_ptr n = a.release(); - dst.link_node_in_bucket(n, dst_bucket); + node::add_to_bucket(n, *dst_bucket); + ++dst.size_; + if(dst_bucket < dst.cached_begin_bucket_) dst.cached_begin_bucket_ = dst_bucket; for(it = next_node(it); it != group_end; it = next_node(it)) { a.construct(node::get_value(it)); - dst.link_node(a.release(), n); + node::add_after_node(a.release(), n); + ++dst.size_; } } }