diff --git a/test/unordered/init_type_insert_tests.cpp b/test/unordered/init_type_insert_tests.cpp index e9920d38..3358ddfe 100644 --- a/test/unordered/init_type_insert_tests.cpp +++ b/test/unordered/init_type_insert_tests.cpp @@ -7,9 +7,16 @@ #error "This test is only for the FOA-style conatiners" #endif +#include "../helpers/test.hpp" #include "../helpers/unordered.hpp" -#include "../helpers/test.hpp" +#include + +#if defined(BOOST_LIBSTDCXX_VERSION) +#if BOOST_LIBSTDCXX_VERSION < 60000 +#define BOOST_UNORDERED_NO_INIT_TYPE_TESTS +#endif +#endif struct move_only { @@ -26,18 +33,49 @@ struct move_only } }; -namespace std{ +namespace std { -template <> struct hash -{ - std::size_t operator()(move_only const& mo) const noexcept + template <> struct hash { - return std::hash()(mo.x_); + std::size_t operator()(move_only const& mo) const noexcept + { + return std::hash()(mo.x_); + } + }; + +} // namespace std + +#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS + +struct immovable +{ + int x_ = -1; + + immovable() = default; + immovable(int x) : x_{x} {} + immovable(immovable const&) = delete; + immovable(immovable&&) = delete; + + friend bool operator==(immovable const& lhs, immovable const& rhs) + { + return lhs.x_ == rhs.x_; } }; +namespace std { + + template <> struct hash + { + std::size_t operator()(immovable const& im) const noexcept + { + return std::hash()(im.x_); + } + }; + } // namespace std +#endif + struct raii_tracker { static unsigned move_constructs; @@ -68,15 +106,15 @@ struct raii_tracker } }; -namespace std{ +namespace std { -template <> struct hash -{ - std::size_t operator()(raii_tracker const& rt) const noexcept + template <> struct hash { - return std::hash()(rt.x_); - } -}; + std::size_t operator()(raii_tracker const& rt) const noexcept + { + return std::hash()(rt.x_); + } + }; } // namespace std @@ -90,9 +128,7 @@ static void test_move_only() boost::unordered_flat_map > map; using init_type = decltype(map)::init_type; - static_assert( - std::is_same::value, - ""); + static_assert(std::is_same, init_type>::value, ""); map.insert(std::make_pair(move_only(1), v)); map.insert({move_only(2), v}); @@ -235,10 +271,167 @@ static void test_insert_hint_tracking() BOOST_TEST_EQ(raii_tracker::move_constructs, 7u + 2u * map.size()); } +static void test_immovable() +{ +#ifndef BOOST_UNORDERED_NO_INIT_TYPE_TESTS + int const v = 128; + + boost::unordered_node_map > map; + + using init_type = decltype(map)::init_type; + static_assert(std::is_same, init_type>::value, ""); + + map.emplace(1, v); + map.emplace(2, v); + + BOOST_TEST_EQ(map.size(), 2u); + + map.rehash(1024); + BOOST_TEST_GE(map.bucket_count(), 1024u); +#endif +} + +static void test_insert_node_tracking() +{ + raii_tracker::reset_counts(); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 0u); + + boost::unordered_node_map > + map; + + { + std::pair value{1, 2}; + + map.insert(value); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 0u); + } + + { + std::pair value{2, 3}; + + map.insert(std::move(value)); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 2u); + } + + { + std::pair value{3, 4}; + + map.insert(value); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 2u); + } + + { + std::pair value{4, 5}; + + map.insert(std::move(value)); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 3u); + } + + { + map.insert(std::make_pair(5, 6)); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 5u); + } + + { + map.insert({6, 7}); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 7u); + } + + BOOST_TEST_EQ(map.size(), 6u); + + map.rehash(1024); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 7u); +} + +static void test_insert_hint_node_tracking() +{ + raii_tracker::reset_counts(); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 0u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 0u); + + boost::unordered_node_map > + map; + + { + std::pair value{1, 2}; + + map.insert(map.begin(), value); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 0u); + } + + { + std::pair value{2, 3}; + + map.insert(std::move(value)); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 2u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 2u); + } + + { + std::pair value{3, 4}; + + map.insert(map.begin(), value); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 4u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 2u); + } + + { + std::pair value{4, 5}; + + map.insert(map.begin(), std::move(value)); + + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 3u); + } + + { + map.insert(map.begin(), std::make_pair(5, 6)); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 5u); + } + + { + map.insert(map.begin(), {6, 7}); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 7u); + } + + BOOST_TEST_EQ(map.size(), 6u); + + map.rehash(1024); + BOOST_TEST_EQ(raii_tracker::copy_constructs, 5u); + BOOST_TEST_EQ(raii_tracker::move_constructs, 7u); +} + int main() { test_move_only(); test_insert_tracking(); test_insert_hint_tracking(); + + test_immovable(); + test_insert_node_tracking(); + test_insert_hint_node_tracking(); + return boost::report_errors(); }