diff --git a/include/boost/unordered/concurrent_flat_map.hpp b/include/boost/unordered/concurrent_flat_map.hpp index 4d5d6d64..0be6fa60 100644 --- a/include/boost/unordered/concurrent_flat_map.hpp +++ b/include/boost/unordered/concurrent_flat_map.hpp @@ -149,8 +149,7 @@ namespace boost { detail::foa::concurrent_table table_; template - bool friend operator==( - concurrent_flat_map const& lhs, + bool friend operator==(concurrent_flat_map const& lhs, concurrent_flat_map const& rhs); public: @@ -747,9 +746,7 @@ namespace boost { /// Hash Policy /// - size_type bucket_count() const noexcept { - return table_.capacity(); - } + size_type bucket_count() const noexcept { return table_.capacity(); } float load_factor() const noexcept { return table_.load_factor(); } float max_load_factor() const noexcept @@ -788,7 +785,16 @@ namespace boost { { return !(lhs == rhs); } + + template + void swap(concurrent_flat_map& x, + concurrent_flat_map& y) + noexcept(noexcept(x.swap(y))) + { + x.swap(y); + } } // namespace unordered + } // namespace boost #undef BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE diff --git a/test/cfoa/swap_tests.cpp b/test/cfoa/swap_tests.cpp index 22cbfded..3ef830f3 100644 --- a/test/cfoa/swap_tests.cpp +++ b/test/cfoa/swap_tests.cpp @@ -83,8 +83,22 @@ BOOST_STATIC_ASSERT(is_nothrow_member_swappable::value); BOOST_STATIC_ASSERT(!is_nothrow_member_swappable::value); namespace { - template - void swap_tests(X*, G gen, test::random_generator rg) + struct + { + template void operator()(T& x1, T& x2) const { x1.swap(x2); } + } member_fn_swap; + + struct + { + template void operator()(T& x1, T& x2) const + { + using boost::unordered::swap; + swap(x1, x2); + } + } free_fn_swap; + + template + void swap_tests(X*, F swapper, G gen, test::random_generator rg) { using allocator = typename X::allocator_type; @@ -118,11 +132,11 @@ namespace { auto const old_cc = +raii::copy_constructor; auto const old_mc = +raii::move_constructor; - thread_runner(vals1, [&x1, &x2](boost::span s) { + thread_runner(vals1, [&x1, &x2, swapper](boost::span s) { (void)s; - x1.swap(x2); - x2.swap(x1); + swapper(x1, x2); + swapper(x2, x1); }); BOOST_TEST_EQ(raii::copy_constructor, old_cc); @@ -163,7 +177,8 @@ namespace { check_raii_counts(); } - template void insert_and_swap(G gen, test::random_generator rg) + template + void insert_and_swap(F swapper, G gen, test::random_generator rg) { auto vals1 = make_random_values(1024 * 8, [&] { return gen(rg); }); auto vals2 = make_random_values(1024 * 4, [&] { return gen(rg); }); @@ -208,20 +223,21 @@ namespace { done2 = true; }); - t3 = std::thread([&x1, &x2, &m, &cv, &done1, &done2, &num_swaps] { - do { - { - std::unique_lock lk(m); - cv.wait(lk, [] { return true; }); - } - x1.swap(x2); - ++num_swaps; - std::this_thread::yield(); - } while (!done1 || !done2); + t3 = + std::thread([&x1, &x2, &m, &cv, &done1, &done2, &num_swaps, swapper] { + do { + { + std::unique_lock lk(m); + cv.wait(lk, [] { return true; }); + } + swapper(x1, x2); + ++num_swaps; + std::this_thread::yield(); + } while (!done1 || !done2); - BOOST_TEST(done1); - BOOST_TEST(done2); - }); + BOOST_TEST(done1); + BOOST_TEST(done2); + }); t1.join(); t2.join(); @@ -258,10 +274,12 @@ namespace { UNORDERED_TEST( swap_tests, ((map)(pocs_map)) + ((member_fn_swap)(free_fn_swap)) ((value_type_generator)) ((default_generator)(sequential)(limited_range))) UNORDERED_TEST(insert_and_swap, + ((member_fn_swap)(free_fn_swap)) ((value_type_generator)) ((default_generator)(sequential)(limited_range))) // clang-format on