diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index c28adcf9..17b73592 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -21,6 +21,7 @@ namespace boost { namespace unordered { namespace detail { class table : public T::buckets, public T::functions { table(table const&); + table& operator=(table const&); public: typedef BOOST_DEDUCED_TYPENAME T::hasher hasher; typedef BOOST_DEDUCED_TYPENAME T::key_equal key_equal; @@ -234,13 +235,6 @@ namespace boost { namespace unordered { namespace detail { ~table() {} - table& operator=(table const& x) - { - table tmp(x, this->node_alloc()); - this->fast_swap(tmp); - return *this; - } - // Iterators node_ptr begin() const { @@ -248,6 +242,48 @@ namespace boost { namespace unordered { namespace detail { node_ptr() : this->buckets_[this->bucket_count_].next_; } + void assign(table const& x) + { + table tmp(x, this->node_alloc()); + this->fast_swap(tmp); + } + + void move_assign(table& x) + { + // This can throw, but it only affects the function objects + // that aren't in use so it is strongly exception safe, via. + // double buffering. + set_hash_functions new_func_this(*this, x); + + if(this->node_alloc() == x.node_alloc()) { + this->buckets::move(x); // no throw + this->size_ = x.size_; + this->max_load_ = x.max_load_; + x.size_ = 0; + } + else { + // Create new buckets in separate buckets + // which will clean up if anything throws an exception. + + buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_)); + if (x.size_) { + // Use a temporary table because move_buckets_to leaves the + // source container in a complete mess. + table tmp(x, move_tag()); + tmp.move_buckets_to(b); + } + + // Start updating the data here, no throw from now on. + this->size_ = x.size_; + b.swap(*this); + this->max_load_ = x.size_ ? calculate_max_load() : 0; + } + + // We've made it, the rest is no throw. + this->mlf_ = x.mlf_; + new_func_this.commit(); + } + //////////////////////////////////////////////////////////////////////// // Swap & Move @@ -295,42 +331,6 @@ namespace boost { namespace unordered { namespace detail { std::swap(this->max_load_, x.max_load_); } - void move(table& x) - { - // This can throw, but it only affects the function objects - // that aren't in use so it is strongly exception safe, via. - // double buffering. - set_hash_functions new_func_this(*this, x); - - if(this->node_alloc() == x.node_alloc()) { - this->buckets::move(x); // no throw - this->size_ = x.size_; - this->max_load_ = x.max_load_; - x.size_ = 0; - } - else { - // Create new buckets in separate buckets - // which will clean up if anything throws an exception. - - buckets b(this->node_alloc(), x.min_buckets_for_size(x.size_)); - if (x.size_) { - // Use a temporary table because move_buckets_to leaves the - // source container in a complete mess. - table tmp(x, move_tag()); - tmp.move_buckets_to(b); - } - - // Start updating the data here, no throw from now on. - this->size_ = x.size_; - b.swap(*this); - this->max_load_ = x.size_ ? calculate_max_load() : 0; - } - - // We've made it, the rest is no throw. - this->mlf_ = x.mlf_; - new_func_this.commit(); - } - //////////////////////////////////////////////////////////////////////// // Key methods diff --git a/include/boost/unordered/unordered_map.hpp b/include/boost/unordered/unordered_map.hpp index da852a1c..389f434f 100644 --- a/include/boost/unordered/unordered_map.hpp +++ b/include/boost/unordered/unordered_map.hpp @@ -129,7 +129,7 @@ namespace unordered unordered_map& operator=( BOOST_COPY_ASSIGN_REF(unordered_map) x) { - table_ = x.table_; + table_.assign(x.table_); return *this; } @@ -139,7 +139,7 @@ namespace unordered unordered_map& operator=( BOOST_RV_REF(unordered_map) x) { - table_.move(x.table_); + table_.move_assign(x.table_); return *this; } @@ -481,7 +481,7 @@ namespace unordered unordered_multimap& operator=( BOOST_COPY_ASSIGN_REF(unordered_multimap) x) { - table_ = x.table_; + table_.assign(x.table_); return *this; } @@ -491,7 +491,7 @@ namespace unordered unordered_multimap& operator=( BOOST_RV_REF(unordered_multimap) x) { - table_.move(x.table_); + table_.move_assign(x.table_); return *this; } diff --git a/include/boost/unordered/unordered_set.hpp b/include/boost/unordered/unordered_set.hpp index a6525187..a42cca30 100644 --- a/include/boost/unordered/unordered_set.hpp +++ b/include/boost/unordered/unordered_set.hpp @@ -128,7 +128,7 @@ namespace unordered unordered_set& operator=( BOOST_COPY_ASSIGN_REF(unordered_set) x) { - table_ = x.table_; + table_.assign(x.table_); return *this; } @@ -138,7 +138,7 @@ namespace unordered unordered_set& operator=( BOOST_RV_REF(unordered_set) x) { - table_.move(x.table_); + table_.move_assign(x.table_); return *this; } @@ -460,7 +460,7 @@ namespace unordered unordered_multiset& operator=( BOOST_COPY_ASSIGN_REF(unordered_multiset) x) { - table_ = x.table_; + table_.assign(x.table_); return *this; } @@ -470,7 +470,7 @@ namespace unordered unordered_multiset& operator=( BOOST_RV_REF(unordered_multiset) x) { - table_.move(x.table_); + table_.move_assign(x.table_); return *this; }