diff --git a/include/boost/unordered/detail/fca.hpp b/include/boost/unordered/detail/fca.hpp index 66c8c250..1f733db2 100644 --- a/include/boost/unordered/detail/fca.hpp +++ b/include/boost/unordered/detail/fca.hpp @@ -659,12 +659,7 @@ namespace boost { std::swap(buckets, other.buckets); std::swap(groups, other.groups); - bool b = boost::allocator_propagate_on_container_swap< - allocator_type>::type::value; - if (b) { - boost::core::invoke_swap( - get_node_allocator(), other.get_node_allocator()); - } + swap_allocator_if_pocs(other); } node_allocator_type const& get_node_allocator() const @@ -876,6 +871,27 @@ namespace boost { pbg->prev->next = pbg->next; pbg->prev = pbg->next = group_pointer(); } + + void swap_allocator_if_pocs(grouped_bucket_array& other) + { + using allocator_pocs = + typename boost::allocator_propagate_on_container_swap< + allocator_type>::type; + swap_allocator_if_pocs( + other, std::integral_constant()); + } + + void swap_allocator_if_pocs( + grouped_bucket_array& other, std::true_type /* propagate */) + { + boost::core::invoke_swap( + get_node_allocator(), other.get_node_allocator()); + } + + void swap_allocator_if_pocs( + grouped_bucket_array&, std::false_type /* don't propagate */) + { + } }; } // namespace detail } // namespace unordered diff --git a/test/unordered/pmr_allocator_tests.cpp b/test/unordered/pmr_allocator_tests.cpp index fd466d19..e458d350 100644 --- a/test/unordered/pmr_allocator_tests.cpp +++ b/test/unordered/pmr_allocator_tests.cpp @@ -180,6 +180,7 @@ namespace pmr_allocator_tests { { copy_op, move_op, + swap_op, }; template void do_operation(X& x1, X& x2, operation op) @@ -191,6 +192,9 @@ namespace pmr_allocator_tests { case move_op: x2 = std::move(x1); return; + case swap_op: + x1.swap(x1); // Swapping with non-equal non-pocs allocators is UB + return; default: BOOST_TEST(false); } @@ -231,7 +235,7 @@ namespace pmr_allocator_tests { UNORDERED_TEST( pmr_no_propagate_on_operation, PMR_ALLOCATOR_TESTS_ARGS - ((copy_op)(move_op)) + ((copy_op)(move_op)(swap_op)) ) // clang-format on