From 7a0a598649131aaec54616dc8736b5cdcab498e6 Mon Sep 17 00:00:00 2001 From: Daniel James Date: Tue, 18 Apr 2017 10:14:26 +0100 Subject: [PATCH] Don't track construction when using boost::tuple Because it doesn't quiet work on C++11 compilers onwards. --- test/helpers/memory.hpp | 39 +++++++++-- test/objects/test.hpp | 12 ++-- test/unordered/insert_tests.cpp | 114 +++++++++++++++++++++++++++++++- 3 files changed, 152 insertions(+), 13 deletions(-) diff --git a/test/helpers/memory.hpp b/test/helpers/memory.hpp index 16837e77..2f910676 100644 --- a/test/helpers/memory.hpp +++ b/test/helpers/memory.hpp @@ -60,9 +60,11 @@ struct memory_tracker unsigned int count_allocators; unsigned int count_allocations; unsigned int count_constructions; + bool tracking_constructions; memory_tracker() - : count_allocators(0), count_allocations(0), count_constructions(0) + : count_allocators(0), count_allocations(0), count_constructions(0), + tracking_constructions(true) { } @@ -133,14 +135,18 @@ struct memory_tracker void track_construct(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) { - ++count_constructions; + if (tracking_constructions) { + ++count_constructions; + } } void track_destroy(void* /*ptr*/, std::size_t /*size*/, int /*tag*/) { - BOOST_TEST(count_constructions > 0); - if (count_constructions > 0) - --count_constructions; + if (tracking_constructions) { + BOOST_TEST(count_constructions > 0); + if (count_constructions > 0) + --count_constructions; + } } }; } @@ -155,6 +161,29 @@ namespace { test::detail::memory_tracker tracker; } } + +namespace detail { +struct disable_construction_tracking +{ + bool old_value; + + disable_construction_tracking() + : old_value(detail::tracker.tracking_constructions) + { + test::detail::tracker.tracking_constructions = false; + } + + ~disable_construction_tracking() + { + test::detail::tracker.tracking_constructions = old_value; + } + + private: + disable_construction_tracking(disable_construction_tracking const&); + disable_construction_tracking& operator=( + disable_construction_tracking const&); +}; +} } #endif diff --git a/test/objects/test.hpp b/test/objects/test.hpp index aba215f0..14f29ab9 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -392,10 +392,10 @@ template class allocator1 } #if BOOST_UNORDERED_CXX11_CONSTRUCTION - template void construct(T* p, Args&&... args) + template void construct(U* p, Args&&... args) { - detail::tracker.track_construct((void*)p, sizeof(T), tag_); - new (p) T(boost::forward(args)...); + detail::tracker.track_construct((void*)p, sizeof(U), tag_); + new (p) U(boost::forward(args)...); } #else void construct(T* p, T const& t) @@ -405,10 +405,10 @@ template class allocator1 } #endif - void destroy(T* p) + template void destroy(U* p) { - detail::tracker.track_destroy((void*)p, sizeof(T), tag_); - p->~T(); + detail::tracker.track_destroy((void*)p, sizeof(U), tag_); + p->~U(); // Work around MSVC buggy unused parameter warning. ignore_variable(&p); diff --git a/test/unordered/insert_tests.cpp b/test/unordered/insert_tests.cpp index 332a9b0f..a53f43c3 100644 --- a/test/unordered/insert_tests.cpp +++ b/test/unordered/insert_tests.cpp @@ -1120,6 +1120,10 @@ struct convertible_to_piecewise UNORDERED_AUTO_TEST(map_emplace_test2) { + // Emulating piecewise construction with boost::tuple bypasses the + // allocator's construct method, but still uses test destroy method. + test::detail::disable_construction_tracking _scoped; + { boost::unordered_map, @@ -1169,8 +1173,8 @@ UNORDERED_AUTO_TEST(map_emplace_test2) x.find(overloaded_constructor(2, 3))->second == overloaded_constructor(4, 5, 6)); } - { + { boost::unordered_multimap, std::equal_to, @@ -1220,9 +1224,115 @@ UNORDERED_AUTO_TEST(set_emplace_test2) boost::make_tuple(2, 3)); check = std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3)); - ; BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check); } + +#if BOOST_UNORDERED_HAVE_PIECEWISE_CONSTRUCT + +UNORDERED_AUTO_TEST(map_std_emplace_test2) +{ + { + boost::unordered_map, + std::equal_to, + test::allocator1 > > + x; + + x.emplace( + std::piecewise_construct, std::make_tuple(), std::make_tuple()); + BOOST_TEST(x.find(overloaded_constructor()) != x.end() && + x.find(overloaded_constructor())->second == + overloaded_constructor()); + + x.emplace( + convertible_to_piecewise(), std::make_tuple(1), std::make_tuple()); + BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() && + x.find(overloaded_constructor(1))->second == + overloaded_constructor()); + + x.emplace(piecewise_rvalue(), std::make_tuple(2, 3), + std::make_tuple(4, 5, 6)); + BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() && + x.find(overloaded_constructor(2, 3))->second == + overloaded_constructor(4, 5, 6)); + + derived_from_piecewise_construct_t d; + x.emplace(d, std::make_tuple(9, 3, 1), std::make_tuple(10)); + BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() && + x.find(overloaded_constructor(9, 3, 1))->second == + overloaded_constructor(10)); + + x.clear(); + + x.try_emplace(overloaded_constructor()); + BOOST_TEST(x.find(overloaded_constructor()) != x.end() && + x.find(overloaded_constructor())->second == + overloaded_constructor()); + + x.try_emplace(1); + BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() && + x.find(overloaded_constructor(1))->second == + overloaded_constructor()); + + x.try_emplace(overloaded_constructor(2, 3), 4, 5, 6); + BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() && + x.find(overloaded_constructor(2, 3))->second == + overloaded_constructor(4, 5, 6)); + } + { + boost::unordered_multimap, + std::equal_to, + test::allocator1 > > + x; + + x.emplace( + std::piecewise_construct, std::make_tuple(), std::make_tuple()); + BOOST_TEST(x.find(overloaded_constructor()) != x.end() && + x.find(overloaded_constructor())->second == + overloaded_constructor()); + + x.emplace( + convertible_to_piecewise(), std::make_tuple(1), std::make_tuple()); + BOOST_TEST(x.find(overloaded_constructor(1)) != x.end() && + x.find(overloaded_constructor(1))->second == + overloaded_constructor()); + + x.emplace(piecewise_rvalue(), std::make_tuple(2, 3), + std::make_tuple(4, 5, 6)); + BOOST_TEST(x.find(overloaded_constructor(2, 3)) != x.end() && + x.find(overloaded_constructor(2, 3))->second == + overloaded_constructor(4, 5, 6)); + + derived_from_piecewise_construct_t d; + x.emplace(d, std::make_tuple(9, 3, 1), std::make_tuple(10)); + BOOST_TEST(x.find(overloaded_constructor(9, 3, 1)) != x.end() && + x.find(overloaded_constructor(9, 3, 1))->second == + overloaded_constructor(10)); + } +} + +UNORDERED_AUTO_TEST(set_std_emplace_test2) +{ + boost::unordered_set< + std::pair > + x; + std::pair check; + + x.emplace(std::piecewise_construct, std::make_tuple(), std::make_tuple()); + BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check); + + x.clear(); + x.emplace( + std::piecewise_construct, std::make_tuple(1), std::make_tuple(2, 3)); + check = + std::make_pair(overloaded_constructor(1), overloaded_constructor(2, 3)); + BOOST_TEST(x.find(check) != x.end() && *x.find(check) == check); +} + +#endif } RUN_TESTS()