diff --git a/doc/changes.qbk b/doc/changes.qbk index acc43088..586656e6 100644 --- a/doc/changes.qbk +++ b/doc/changes.qbk @@ -265,5 +265,6 @@ C++11 support has resulted in some breaking changes: confuses some traits classes. * Fix move assignment with stateful, propagate_on_container_move_assign allocators ([ticket 10777]). +* Fix rare exception safety issue in move assignment. [endsect] diff --git a/include/boost/unordered/detail/table.hpp b/include/boost/unordered/detail/table.hpp index 87012b5e..172739e3 100644 --- a/include/boost/unordered/detail/table.hpp +++ b/include/boost/unordered/detail/table.hpp @@ -712,15 +712,25 @@ namespace boost { namespace unordered { namespace detail { void move_assign(table& x, true_type) { delete_buckets(); + set_hash_functions new_func_this(*this, x); allocators_.move_assign(x.allocators_); - move_assign_no_alloc(x); + // No throw from here. + mlf_ = x.mlf_; + max_load_ = x.max_load_; + move_buckets_from(x); + new_func_this.commit(); } void move_assign(table& x, false_type) { if (node_alloc() == x.node_alloc()) { delete_buckets(); - move_assign_no_alloc(x); + set_hash_functions new_func_this(*this, x); + // No throw from here. + mlf_ = x.mlf_; + max_load_ = x.max_load_; + move_buckets_from(x); + new_func_this.commit(); } else { set_hash_functions new_func_this(*this, x); @@ -745,16 +755,6 @@ namespace boost { namespace unordered { namespace detail { table_impl::fill_buckets(nodes.begin(), *this, node_creator); } } - - void move_assign_no_alloc(table& x) - { - set_hash_functions new_func_this(*this, x); - // No throw from here. - mlf_ = x.mlf_; - max_load_ = x.max_load_; - move_buckets_from(x); - new_func_this.commit(); - } // Accessors