diff --git a/include/boost/unordered/detail/foa.hpp b/include/boost/unordered/detail/foa.hpp index 1ea4b3e0..2ec0892f 100644 --- a/include/boost/unordered/detail/foa.hpp +++ b/include/boost/unordered/detail/foa.hpp @@ -824,6 +824,32 @@ using table_arrays=typename std::conditional< aligned_table_arrays, subaligned_table_arrays>::type; +struct if_constexpr_void_else{void operator()()const{}}; + +template +void if_constexpr(F f,G g={}) +{ + std::get(std::forward_as_tuple(f,g))(); +} + +template::type* =nullptr> +void copy_assign_if(T& x,const T& y){x=y;} + +template::type* =nullptr> +void copy_assign_if(T& x,const T& y){} + +template::type* =nullptr> +void move_assign_if(T& x,T& y){x=std::move(y);} + +template::type* =nullptr> +void move_assign_if(T& x,T& y){} + +template::type* =nullptr> +void swap_if(T& x,T& y){using std::swap; swap(x,y);} + +template::type* =nullptr> +void swap_if(T& x,T& y){} + #if defined(BOOST_GCC) /* GCC's -Wshadow triggers at scenarios like this: * @@ -975,31 +1001,19 @@ public: delete_arrays(arrays); } - template - typename std::enable_if< - !AllocTraits::propagate_on_container_copy_assignment::value, - void - >::type - copy_assign_helper(const table&) {} - - template - typename std::enable_if< - AllocTraits::propagate_on_container_copy_assignment::value, - void - >::type - copy_assign_helper(const table& x) - { - if(al()!=x.al())reserve(0); - al()=x.al(); - } - table& operator=(const table& x) { + static constexpr auto pocca= + alloc_traits::propagate_on_container_copy_assignment::value; + if(this!=&x){ clear(); h()=x.h(); pred()=x.pred(); - copy_assign_helper(x); + if_constexpr([&,this]{ + if(al()!=x.al())reserve(0); + copy_assign_if(al(),x.al()); + }); // TODO may shrink arrays and miss an opportunity for memory reuse reserve(x.size()); x.for_all_elements([this](value_type* p){ @@ -1020,9 +1034,10 @@ public: std::is_nothrow_move_assignable::value&& std::is_nothrow_move_assignable::value) { + static constexpr auto pocma= + alloc_traits::propagate_on_container_move_assignment::value; + if(this!=&x){ - // TODO explain why not constexpr - auto pocma=alloc_traits::propagate_on_container_move_assignment::value; clear(); h()=std::move(x.h()); pred()=std::move(x.pred()); @@ -1031,7 +1046,7 @@ public: reserve(0); swap(arrays,x.arrays); swap(ml,x.ml); - if(pocma)al()=std::move(x.al()); + move_assign_if(al(),x.al()); } else{ reserve(x.size()); @@ -1136,11 +1151,18 @@ public: boost::is_nothrow_swappable::value&& boost::is_nothrow_swappable::value) { + static constexpr auto pocs= + alloc_traits::propagate_on_container_swap::value; + using std::swap; swap(h(),x.h()); swap(pred(),x.pred()); - if(alloc_traits::propagate_on_container_swap::value)swap(al(),x.al()); - else BOOST_ASSERT(al()==x.al()); + if_constexpr([&,this]{ + swap_if(al(),x.al()); + }, + [&,this]{ /* else */ + BOOST_ASSERT(al()==x.al()); + }); swap(size_,x.size_); swap(arrays,x.arrays); swap(ml,x.ml);