diff --git a/include/boost/unordered/concurrent_flat_map.hpp b/include/boost/unordered/concurrent_flat_map.hpp index 3eaa731e..aa699844 100644 --- a/include/boost/unordered/concurrent_flat_map.hpp +++ b/include/boost/unordered/concurrent_flat_map.hpp @@ -369,7 +369,7 @@ namespace boost { void insert(InputIterator begin, InputIterator end) { for (auto pos = begin; pos != end; ++pos) { - table_.insert(*pos); + table_.emplace(*pos); } } @@ -421,7 +421,7 @@ namespace boost { { BOOST_UNORDERED_STATIC_ASSERT_INVOCABLE(F) for (; first != last; ++first) { - table_.insert_or_visit(*first, f); + table_.emplace_or_visit(*first, f); } } @@ -452,7 +452,7 @@ namespace boost { { BOOST_UNORDERED_STATIC_ASSERT_CONST_INVOCABLE(F) for (; first != last; ++first) { - table_.insert_or_cvisit(*first, f); + table_.emplace_or_cvisit(*first, f); } } diff --git a/test/cfoa/assign_tests.cpp b/test/cfoa/assign_tests.cpp index a023cb54..aa17e0ac 100644 --- a/test/cfoa/assign_tests.cpp +++ b/test/cfoa/assign_tests.cpp @@ -157,7 +157,10 @@ namespace { thread_runner(values, [&x, &values](boost::span s) { (void)s; - map_type y(values.begin(), values.end(), values.size()); + map_type y(values.size()); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(x.empty()); BOOST_TEST(!y.empty()); @@ -183,8 +186,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_cc = +raii::copy_constructor; @@ -218,8 +223,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_size = x.size(); auto const old_cc = +raii::copy_constructor; @@ -227,7 +234,10 @@ namespace { thread_runner(values, [&x, &values](boost::span s) { (void)s; - map_type y(values.begin(), values.end(), values.size()); + map_type y(values.size()); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(!x.empty()); BOOST_TEST(!y.empty()); @@ -251,8 +261,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_cc = +raii::copy_constructor; @@ -288,8 +300,11 @@ namespace { raii::reset_counts(); - pocca_map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), pocca_allocator_type(3)); + pocca_map_type x( + values.size(), hasher(1), key_equal(2), pocca_allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_size = x.size(); auto const old_cc = +raii::copy_constructor; @@ -297,7 +312,10 @@ namespace { thread_runner(values, [&x, &values](boost::span s) { (void)s; - pocca_map_type y(values.begin(), values.end(), values.size()); + pocca_map_type y(values.size()); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(!x.empty()); BOOST_TEST(!y.empty()); @@ -410,8 +428,10 @@ namespace { values, [&x, &values, &num_transfers](boost::span s) { (void)s; - map_type y(values.begin(), values.end(), values.size(), hasher(2), - key_equal(1), allocator_type(3)); + map_type y(values.size(), hasher(2), key_equal(1), allocator_type(3)); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(x.empty()); BOOST_TEST(!y.empty()); @@ -447,8 +467,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_cc = +raii::copy_constructor; auto const old_mc = +raii::move_constructor; @@ -496,8 +518,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_size = x.size(); auto const old_cc = +raii::copy_constructor; @@ -509,8 +533,10 @@ namespace { boost::span s) { (void)s; - map_type y(values.begin(), values.end(), values.size(), hasher(2), - key_equal(1), allocator_type(3)); + map_type y(values.size(), hasher(2), key_equal(1), allocator_type(3)); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(!y.empty()); BOOST_TEST(x.get_allocator() == y.get_allocator()); @@ -549,8 +575,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_size = x.size(); auto const old_cc = +raii::copy_constructor; @@ -562,8 +590,10 @@ namespace { boost::span s) { (void)s; - map_type y(values.begin(), values.end(), values.size(), hasher(2), - key_equal(1), allocator_type(13)); + map_type y(values.size(), hasher(2), key_equal(1), allocator_type(13)); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST( !boost::allocator_is_always_equal::type::value); @@ -608,8 +638,11 @@ namespace { { raii::reset_counts(); - pocma_map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), pocma_allocator_type(3)); + pocma_map_type x( + values.size(), hasher(1), key_equal(2), pocma_allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_size = x.size(); auto const old_cc = +raii::copy_constructor; @@ -621,8 +654,11 @@ namespace { boost::span s) { (void)s; - pocma_map_type y(values.begin(), values.end(), values.size(), hasher(2), - key_equal(1), pocma_allocator_type(13)); + pocma_map_type y( + values.size(), hasher(2), key_equal(1), pocma_allocator_type(13)); + for (auto const& v : values) { + y.insert(v); + } BOOST_TEST(!y.empty()); BOOST_TEST(x.get_allocator() != y.get_allocator()); @@ -661,8 +697,10 @@ namespace { { raii::reset_counts(); - map_type x(values.begin(), values.end(), values.size(), hasher(1), - key_equal(2), allocator_type(3)); + map_type x(values.size(), hasher(1), key_equal(2), allocator_type(3)); + for (auto const& v : values) { + x.insert(v); + } auto const old_cc = +raii::copy_constructor; auto const old_mc = +raii::move_constructor; diff --git a/test/cfoa/clear_tests.cpp b/test/cfoa/clear_tests.cpp index c72b8155..79240db3 100644 --- a/test/cfoa/clear_tests.cpp +++ b/test/cfoa/clear_tests.cpp @@ -31,8 +31,8 @@ namespace { map_type x(values.begin(), values.end(), values.size(), hasher(1), key_equal(2), allocator_type(3)); - BOOST_TEST_EQ(raii::copy_constructor, 2 * x.size()); - BOOST_TEST_EQ(raii::destructor, 0u); + auto const old_size = x.size(); + auto const old_d = +raii::destructor; thread_runner(values, [&x](boost::span s) { (void)s; @@ -40,6 +40,7 @@ namespace { }); BOOST_TEST(x.empty()); + BOOST_TEST_EQ(raii::destructor, old_d + 2 * old_size); check_raii_counts(); } diff --git a/test/cfoa/constructor_tests.cpp b/test/cfoa/constructor_tests.cpp index 1256fa7e..f6e0e069 100644 --- a/test/cfoa/constructor_tests.cpp +++ b/test/cfoa/constructor_tests.cpp @@ -605,6 +605,7 @@ namespace { } UNORDERED_AUTO_TEST (initializer_list_with_all_params) { + // hard-code 11 unique values std::initializer_list ilist{ map_value_type{raii{0}, raii{0}}, map_value_type{raii{1}, raii{1}}, @@ -640,7 +641,9 @@ namespace { BOOST_TEST_EQ(x.key_eq(), key_equal(2)); BOOST_TEST(x.get_allocator() == allocator_type(3)); - BOOST_TEST_EQ(raii::move_constructor, 0u); + BOOST_TEST_EQ(raii::default_constructor, 0u); + BOOST_TEST_EQ(raii::copy_constructor, 2 * ilist.size()); + BOOST_TEST_EQ(raii::move_constructor, 2 * 11u); } check_raii_counts(); @@ -654,7 +657,9 @@ namespace { BOOST_TEST_EQ(x.key_eq(), key_equal()); BOOST_TEST(x.get_allocator() == allocator_type(3)); - BOOST_TEST_EQ(raii::move_constructor, 0u); + BOOST_TEST_EQ(raii::default_constructor, 0u); + BOOST_TEST_EQ(raii::copy_constructor, 2 * ilist.size()); + BOOST_TEST_EQ(raii::move_constructor, 2 * 11u); } check_raii_counts(); @@ -668,7 +673,9 @@ namespace { BOOST_TEST_EQ(x.key_eq(), key_equal()); BOOST_TEST(x.get_allocator() == allocator_type(3)); - BOOST_TEST_EQ(raii::move_constructor, 0u); + BOOST_TEST_EQ(raii::default_constructor, 0u); + BOOST_TEST_EQ(raii::copy_constructor, 2 * ilist.size()); + BOOST_TEST_EQ(raii::move_constructor, 2 * 11u); } check_raii_counts(); @@ -682,7 +689,9 @@ namespace { BOOST_TEST_EQ(x.key_eq(), key_equal()); BOOST_TEST(x.get_allocator() == allocator_type(3)); - BOOST_TEST_EQ(raii::move_constructor, 0u); + BOOST_TEST_EQ(raii::default_constructor, 0u); + BOOST_TEST_EQ(raii::copy_constructor, 2 * ilist.size()); + BOOST_TEST_EQ(raii::move_constructor, 2 * 11u); } check_raii_counts(); } diff --git a/test/cfoa/exception_erase_tests.cpp b/test/cfoa/exception_erase_tests.cpp index 39ff0212..11d167e7 100644 --- a/test/cfoa/exception_erase_tests.cpp +++ b/test/cfoa/exception_erase_tests.cpp @@ -227,7 +227,9 @@ namespace { { X x(values.size()); - x.insert(values.begin(), values.end()); + for (auto const& v : values) { + x.insert(v); + } BOOST_TEST_EQ(x.size(), reference_map.size()); BOOST_TEST_EQ(raii::destructor, 0u); diff --git a/test/cfoa/insert_tests.cpp b/test/cfoa/insert_tests.cpp index 6aaaf497..f773edf9 100644 --- a/test/cfoa/insert_tests.cpp +++ b/test/cfoa/insert_tests.cpp @@ -8,6 +8,14 @@ #include +struct raii_convertible +{ + int x, y; + raii_convertible(int x_, int y_) : x{x_}, y{y_} {} + + operator std::pair() { return {x, y}; } +}; + namespace { test::seed_t initialize_seed(78937); @@ -95,9 +103,18 @@ namespace { { template void operator()(std::vector& values, X& x) { - thread_runner( - values, [&x](boost::span s) { x.insert(s.begin(), s.end()); }); + std::vector values2; + values2.reserve(values.size()); + for (auto const& p : values) { + values2.push_back(raii_convertible(p.first.x_, p.second.x_)); + } + thread_runner(values2, [&x](boost::span s) { + x.insert(s.begin(), s.end()); + }); + + BOOST_TEST_EQ(raii::default_constructor, 2 * values2.size()); + BOOST_TEST_EQ(raii::copy_constructor, 0u); BOOST_TEST_EQ(raii::copy_assignment, 0u); BOOST_TEST_EQ(raii::move_assignment, 0u); } @@ -361,19 +378,26 @@ namespace { { template void operator()(std::vector& values, X& x) { + std::vector values2; + values2.reserve(values.size()); + for (auto const& p : values) { + values2.push_back(raii_convertible(p.first.x_, p.second.x_)); + } + std::atomic num_invokes{0}; - thread_runner(values, [&x, &num_invokes](boost::span s) { - x.insert_or_cvisit( - s.begin(), s.end(), [&num_invokes](typename X::value_type const& v) { - (void)v; - ++num_invokes; - }); - }); + thread_runner( + values2, [&x, &num_invokes](boost::span s) { + x.insert_or_cvisit(s.begin(), s.end(), + [&num_invokes](typename X::value_type const& v) { + (void)v; + ++num_invokes; + }); + }); BOOST_TEST_EQ(num_invokes, values.size() - x.size()); - BOOST_TEST_EQ(raii::default_constructor, 0u); - BOOST_TEST_EQ(raii::copy_constructor, 2 * x.size()); + BOOST_TEST_EQ(raii::default_constructor, 2 * values2.size()); + BOOST_TEST_EQ(raii::copy_constructor, 0u); BOOST_TEST_GT(raii::move_constructor, 0u); } } iterator_range_insert_or_cvisit; @@ -382,19 +406,26 @@ namespace { { template void operator()(std::vector& values, X& x) { + std::vector values2; + values2.reserve(values.size()); + for (auto const& p : values) { + values2.push_back(raii_convertible(p.first.x_, p.second.x_)); + } + std::atomic num_invokes{0}; - thread_runner(values, [&x, &num_invokes](boost::span s) { - x.insert_or_visit( - s.begin(), s.end(), [&num_invokes](typename X::value_type const& v) { - (void)v; - ++num_invokes; - }); - }); + thread_runner( + values2, [&x, &num_invokes](boost::span s) { + x.insert_or_visit(s.begin(), s.end(), + [&num_invokes](typename X::value_type const& v) { + (void)v; + ++num_invokes; + }); + }); BOOST_TEST_EQ(num_invokes, values.size() - x.size()); - BOOST_TEST_EQ(raii::default_constructor, 0u); - BOOST_TEST_EQ(raii::copy_constructor, 2 * x.size()); + BOOST_TEST_EQ(raii::default_constructor, 2 * values2.size()); + BOOST_TEST_EQ(raii::copy_constructor, 0u); BOOST_TEST_GT(raii::move_constructor, 0u); } } iterator_range_insert_or_visit; diff --git a/test/cfoa/merge_tests.cpp b/test/cfoa/merge_tests.cpp index 2691c09d..92770ecb 100644 --- a/test/cfoa/merge_tests.cpp +++ b/test/cfoa/merge_tests.cpp @@ -63,7 +63,10 @@ namespace { using map2_type = boost::unordered::concurrent_flat_map, std::equal_to, allocator_type>; - map2_type y(s.begin(), s.end(), s.size(), allocator_type(3)); + map2_type y(s.size(), allocator_type(3)); + for (auto const& v : s) { + y.insert(v); + } expected_copies += 2 * y.size(); BOOST_TEST(x.get_allocator() == y.get_allocator());