From 260b573d8dddda9e200f062b28a1e81a3da80a06 Mon Sep 17 00:00:00 2001 From: Christian Mazakas Date: Thu, 1 Dec 2022 14:32:07 -0800 Subject: [PATCH] Update FOA implementation to exhibit strong guarantee for Hash, KeyEqual in copy assignment --- include/boost/unordered/detail/foa.hpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/include/boost/unordered/detail/foa.hpp b/include/boost/unordered/detail/foa.hpp index e70c6ce5..9b3fec58 100644 --- a/include/boost/unordered/detail/foa.hpp +++ b/include/boost/unordered/detail/foa.hpp @@ -1266,13 +1266,28 @@ public: table& operator=(const table& x) { + BOOST_UNORDERED_STATIC_ASSERT_HASH_PRED(Hash, Pred) + static constexpr auto pocca= alloc_traits::propagate_on_container_copy_assignment::value; if(this!=std::addressof(x)){ - clear(); - h()=x.h(); - pred()=x.pred(); + // if copy construction here winds up throwing, the container is still + // left intact so we perform these operations first + hasher tmp_h=x.h(); + key_equal tmp_p=x.pred(); + + // already noexcept, clear() before we swap the Hash, Pred just in case + // the clear() impl relies on them at some point in the future + clear(); + + // because we've asserted at compile-time that Hash and Pred are nothrow + // swappable, we can safely mutate our source container and maintain + // consistency between the Hash, Pred compatibility + using std::swap; + swap(h(),tmp_h); + swap(pred(),tmp_p); + if_constexpr([&,this]{ if(al()!=x.al())reserve(0); copy_assign_if(al(),x.al());