diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index 3385658e..5574c158 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -346,19 +346,20 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) template inline typename enable_if, void>::type - construct_impl(std::pair* address, A0&&, A1&& a1, A2&& a2) + construct_impl(std::pair* address, + BOOST_FWD_REF(A0), BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { boost::unordered::detail::construct_from_tuple( - boost::addressof(address->first), a1); + boost::addressof(address->first), boost::forward(a1)); boost::unordered::detail::construct_from_tuple( - boost::addressof(address->second), a2); + boost::addressof(address->second), boost::forward(a2)); } #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template inline typename enable_if, void>::type - construct_impl(std::pair* address, A0&& a0) + construct_impl(std::pair* address, BOOST_FWD_REF(A0) a0) { new((void*) boost::addressof(address->first)) A(boost::forward(a0)); new((void*) boost::addressof(address->second)) B(); @@ -366,7 +367,8 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) template inline typename enable_if, void>::type - construct_impl(std::pair* address, A0&& a0, A1&& a1, A2&& a2) + construct_impl(std::pair* address, + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2) { new((void*) boost::addressof(address->first)) A(boost::forward(a0)); new((void*) boost::addressof(address->second)) B( @@ -378,7 +380,8 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) typename A0, typename A1, typename A2, typename A3, typename... Args> inline void construct_impl(std::pair* address, - A0&& a0, A1&& a1, A2&& a2, A3&& a3, Args&&... args) + BOOST_FWD_REF(A0) a0, BOOST_FWD_REF(A1) a1, BOOST_FWD_REF(A2) a2, + BOOST_FWD_REF(A3) a3, BOOST_FWD_REF(Args)... args) { new((void*) boost::addressof(address->first)) A(boost::forward(a0)); @@ -390,6 +393,7 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) } #endif // BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT + #else // BOOST_NO_VARIADIC_TEMPLATES //////////////////////////////////////////////////////////////////////////////// @@ -441,9 +445,9 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) #undef BOOST_UNORDERED_CONSTRUCT_IMPL template - inline typename enable_if, void>::type - construct_impl(std::pair* address, - boost::unordered::detail::emplace_args3 const& args) + inline void construct_impl(std::pair* address, + boost::unordered::detail::emplace_args3 const& args, + typename enable_if, void*>::type = 0) { boost::unordered::detail::construct_from_tuple( boost::addressof(address->first), args.a1); @@ -454,9 +458,9 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) #if defined(BOOST_UNORDERED_DEPRECATED_PAIR_CONSTRUCT) template - inline typename enable_if, void>::type - construct_impl(std::pair* address, - boost::unordered::detail::emplace_args1 const& args) + inline void construct_impl(std::pair* address, + boost::unordered::detail::emplace_args1 const& args, + typename enable_if, void*>::type = 0) { new((void*) boost::addressof(address->first)) A( boost::forward(args.a0)); @@ -464,9 +468,9 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) } template - inline typename enable_if, void>::type - construct_impl(std::pair* address, - boost::unordered::detail::emplace_args3 const& args) + inline void construct_impl(std::pair* address, + boost::unordered::detail::emplace_args3 const& args, + typename enable_if, void*>::type = 0) { new((void*) boost::addressof(address->first)) A( boost::forward(args.a0)); @@ -811,35 +815,38 @@ namespace boost { namespace unordered { namespace detail { # endif template - inline typename boost::enable_if_c< + inline Alloc call_select_on_container_copy_construction(const Alloc& rhs, + typename boost::enable_if_c< boost::unordered::detail:: - has_select_on_container_copy_construction::value, Alloc - >::type call_select_on_container_copy_construction(const Alloc& rhs) + has_select_on_container_copy_construction::value, void* + >::type = 0) { return rhs.select_on_container_copy_construction(); } template - inline typename boost::disable_if_c< + inline Alloc call_select_on_container_copy_construction(const Alloc& rhs, + typename boost::disable_if_c< boost::unordered::detail:: - has_select_on_container_copy_construction::value, Alloc - >::type call_select_on_container_copy_construction(const Alloc& rhs) + has_select_on_container_copy_construction::value, void* + >::type = 0) { return rhs; } template - inline typename boost::enable_if_c< - boost::unordered::detail::has_max_size::value, SizeType - >::type call_max_size(const Alloc& a) + inline SizeType call_max_size(const Alloc& a, + typename boost::enable_if_c< + boost::unordered::detail::has_max_size::value, void* + >::type = 0) { return a.max_size(); } template - inline typename boost::disable_if_c< - boost::unordered::detail::has_max_size::value, SizeType - >::type call_max_size(const Alloc&) + inline SizeType call_max_size(const Alloc&, typename boost::disable_if_c< + boost::unordered::detail::has_max_size::value, void* + >::type = 0) { return (std::numeric_limits::max)(); } @@ -967,41 +974,41 @@ namespace boost { namespace unordered { namespace detail { // the only construct method that old fashioned allocators support. template - static typename boost::enable_if_c< - boost::unordered::detail::has_construct::value && - boost::is_same::value - >::type - construct(Alloc& a, T* p, T const& x) + static void construct(Alloc& a, T* p, T const& x, + typename boost::enable_if_c< + boost::unordered::detail::has_construct::value && + boost::is_same::value, + void*>::type = 0) { a.construct(p, x); } template - static typename boost::disable_if_c< + static void construct(Alloc&, T* p, T const& x, + typename boost::disable_if_c< boost::unordered::detail::has_construct::value && - boost::is_same::value - >::type - construct(Alloc&, T* p, T const& x) + boost::is_same::value, + void*>::type = 0) { new ((void*) p) T(x); } template - static typename boost::enable_if_c< + static void destroy(Alloc& a, T* p, + typename boost::enable_if_c< boost::unordered::detail::has_destroy::value && - boost::is_same::value - >::type - destroy(Alloc& a, T* p) + boost::is_same::value, + void*>::type = 0) { a.destroy(p); } template - static typename boost::disable_if_c< + static void destroy(Alloc&, T* p, + typename boost::disable_if_c< boost::unordered::detail::has_destroy::value && - boost::is_same::value - >::type - destroy(Alloc&, T* p) + boost::is_same::value, + void*>::type = 0) { boost::unordered::detail::destroy(p); } @@ -1120,17 +1127,42 @@ namespace boost { namespace unordered { namespace detail { #else + template + struct value_construct + { + typedef BOOST_DEDUCED_TYPENAME AllocTraits::allocator_type allocator; + + allocator& alloc; + T* ptr; + + value_construct(allocator& a, T* p) : alloc(a), ptr(p) + { + AllocTraits::construct(alloc, ptr, T()); + } + + void release() + { + ptr = 0; + } + + ~value_construct() + { + if (ptr) AllocTraits::destroy(alloc, ptr); + } + + private: + value_construct(value_construct const&); + value_construct& operator=(value_construct const&); + }; + template inline void construct_node(Alloc& a, T* p, BOOST_UNORDERED_EMPLACE_ARGS) { - boost::unordered::detail::allocator_traits::construct(a, p, T()); - try { - boost::unordered::detail::construct_impl( - p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); - } catch(...) { - boost::unordered::detail::allocator_traits::destroy(a, p); - throw; - } + value_construct, T> + construct_guard(a, p); + boost::unordered::detail::construct_impl( + p->value_ptr(), BOOST_UNORDERED_EMPLACE_FORWARD); + construct_guard.release(); } template diff --git a/test/objects/test.hpp b/test/objects/test.hpp index 2a1dfbdf..ce9c698b 100644 --- a/test/objects/test.hpp +++ b/test/objects/test.hpp @@ -26,7 +26,9 @@ namespace test template class allocator2; object generate(object const*); implicitly_convertible generate(implicitly_convertible const*); - + + inline void ignore_variable(void const*) {} + class object : private counted_object { friend class hash; @@ -248,6 +250,9 @@ namespace test void destroy(T* p) { //detail::tracker.track_destroy((void*) p, sizeof(T), tag_); p->~T(); + + // Work around MSVC buggy unused parameter warning. + ignore_variable(&p); } bool operator==(allocator1 const& x) const diff --git a/test/unordered/at_tests.cpp b/test/unordered/at_tests.cpp index 111f9c2f..cd272679 100644 --- a/test/unordered/at_tests.cpp +++ b/test/unordered/at_tests.cpp @@ -13,21 +13,31 @@ namespace at_tests { UNORDERED_AUTO_TEST(at_tests) { + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Create Map" << std::endl; + boost::unordered_map x; typedef boost::unordered_map::iterator iterator; + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Add elements" << std::endl; + x["one"] = 1; x["two"] = 2; + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check existing elements" << std::endl; + BOOST_TEST(x.at("one") == 1); BOOST_TEST(x.at("two") == 2); + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Check missing element" << std::endl; + try { x.at("three"); BOOST_ERROR("Should have thrown."); } catch(std::out_of_range) { } + + BOOST_LIGHTWEIGHT_TEST_OSTREAM << "Finished" << std::endl; } }