diff --git a/include/boost/unordered/detail/foa.hpp b/include/boost/unordered/detail/foa.hpp index 9537e9a3..f2867074 100644 --- a/include/boost/unordered/detail/foa.hpp +++ b/include/boost/unordered/detail/foa.hpp @@ -1256,7 +1256,14 @@ public: template BOOST_FORCEINLINE std::pair emplace(Args&&... args) { - return emplace_impl(init_type(std::forward(args)...)); + using emplace_type = typename std::conditional< + std::is_constructible< + init_type, Args... + >::value, + init_type, + value_type + >::type; + return emplace_impl(emplace_type(std::forward(args)...)); } template diff --git a/include/boost/unordered/unordered_flat_map.hpp b/include/boost/unordered/unordered_flat_map.hpp index 77431650..2cb4135e 100644 --- a/include/boost/unordered/unordered_flat_map.hpp +++ b/include/boost/unordered/unordered_flat_map.hpp @@ -242,7 +242,7 @@ namespace boost { void insert(InputIterator first, InputIterator last) { for (auto pos = first; pos != last; ++pos) { - table_.insert(*pos); + table_.emplace(*pos); } } diff --git a/include/boost/unordered/unordered_flat_set.hpp b/include/boost/unordered/unordered_flat_set.hpp index fae770ee..f0129485 100644 --- a/include/boost/unordered/unordered_flat_set.hpp +++ b/include/boost/unordered/unordered_flat_set.hpp @@ -222,7 +222,7 @@ namespace boost { void insert(InputIterator first, InputIterator last) { for (auto pos = first; pos != last; ++pos) { - table_.insert(*pos); + table_.emplace(*pos); } } diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index b37b20ca..f59d5acd 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -17,6 +17,8 @@ #include "../helpers/input_iterator.hpp" #include "../helpers/helpers.hpp" +#include + namespace insert_tests { test::seed_t initialize_seed(243432); @@ -674,6 +676,23 @@ namespace insert_tests { } } + template void set_tests(X*, test::random_generator) + { + // prove that our insert(iterator, iterator) implementation honors + // Cpp17EmplaceConstructible + // + + X x; + std::vector v; + v.reserve(1000); + for (unsigned i = 0; i < 1000; ++i) { + v.push_back(static_cast(i)); + } + + x.insert(v.begin(), v.end()); + BOOST_TEST_EQ(x.size(), 1000u); + } + template void try_emplace_tests(X*, test::random_generator generator) { @@ -909,6 +928,9 @@ namespace insert_tests { UNORDERED_TEST(map_insert_range_test2, ((test_map))((default_generator)(generate_collisions)(limited_range))) + + UNORDERED_TEST( + set_tests, ((test_set_std_alloc)(test_set))((default_generator))) #else boost::unordered_set >* test_set_std_alloc; @@ -965,6 +987,9 @@ namespace insert_tests { UNORDERED_TEST(map_insert_range_test2, ((test_multimap_std_alloc)(test_map)(test_multimap))( (default_generator)(generate_collisions)(limited_range))) + + UNORDERED_TEST( + set_tests, ((test_set_std_alloc)(test_set)(test_multiset))((default_generator))) #endif #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST)