diff --git a/include/boost/unordered/detail/allocate.hpp b/include/boost/unordered/detail/allocate.hpp index 8e4f8694..2da85be8 100644 --- a/include/boost/unordered/detail/allocate.hpp +++ b/include/boost/unordered/detail/allocate.hpp @@ -1118,10 +1118,19 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) boost::unordered::detail::func::const_cast_pointer( boost::addressof(address->first)), boost::forward(a1)); - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->second)), - boost::forward(a2)); + BOOST_TRY { + boost::unordered::detail::func::construct_from_tuple(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(address->second)), + boost::forward(a2)); + } + BOOST_CATCH(...) { + boost::unordered::detail::func::call_destroy(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(address->first))); + BOOST_RETHROW; + } + BOOST_CATCH_END } #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES @@ -1194,10 +1203,19 @@ BOOST_UNORDERED_CONSTRUCT_FROM_TUPLE(10, boost::) boost::unordered::detail::func::const_cast_pointer( boost::addressof(address->first)), args.a1); - boost::unordered::detail::func::construct_from_tuple(alloc, - boost::unordered::detail::func::const_cast_pointer( - boost::addressof(address->second)), - args.a2); + BOOST_TRY { + boost::unordered::detail::func::construct_from_tuple(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(address->second)), + args.a2); + } + BOOST_CATCH(...) { + boost::unordered::detail::func::call_destroy(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(address->first))); + BOOST_RETHROW; + } + BOOST_CATCH_END } #endif // BOOST_NO_CXX11_VARIADIC_TEMPLATES @@ -1362,9 +1380,18 @@ namespace boost { namespace unordered { namespace detail { namespace func { boost::unordered::detail::func::const_cast_pointer( boost::addressof(a.node_->value_ptr()->first)), boost::forward(k)); - boost::unordered::detail::func::call_construct(alloc, + BOOST_TRY { + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->second))); + } + BOOST_CATCH(...) { + boost::unordered::detail::func::call_destroy(alloc, boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->second))); + boost::addressof(a.node_->value_ptr()->first))); + BOOST_RETHROW; + } + BOOST_CATCH_END return a.release(); } @@ -1378,10 +1405,19 @@ namespace boost { namespace unordered { namespace detail { namespace func { boost::unordered::detail::func::const_cast_pointer( boost::addressof(a.node_->value_ptr()->first)), boost::forward(k)); - boost::unordered::detail::func::call_construct(alloc, + BOOST_TRY { + boost::unordered::detail::func::call_construct(alloc, + boost::unordered::detail::func::const_cast_pointer( + boost::addressof(a.node_->value_ptr()->second)), + boost::forward(m)); + } + BOOST_CATCH(...) { + boost::unordered::detail::func::call_destroy(alloc, boost::unordered::detail::func::const_cast_pointer( - boost::addressof(a.node_->value_ptr()->second)), - boost::forward(m)); + boost::addressof(a.node_->value_ptr()->first))); + BOOST_RETHROW; + } + BOOST_CATCH_END return a.release(); } }}}} diff --git a/test/exception/containers.hpp b/test/exception/containers.hpp index 1e379645..ee938330 100644 --- a/test/exception/containers.hpp +++ b/test/exception/containers.hpp @@ -31,5 +31,17 @@ typedef boost::unordered_multimap< test::exception::hash, test::exception::equal_to, test::exception::allocator > test_multimap; +typedef boost::unordered_set< + std::pair, + test::exception::hash, + test::exception::equal_to, + test::exception::allocator > test_pair_set; +typedef boost::unordered_multiset< + std::pair, + test::exception::hash, + test::exception::equal_to, + test::exception::allocator2 > test_pair_multiset; + #define CONTAINER_SEQ (test_set)(test_multiset)(test_map)(test_multimap) +#define CONTAINER_PAIR_SEQ (test_pair_set)(test_pair_multiset)(test_map)(test_multimap) diff --git a/test/exception/insert_exception_tests.cpp b/test/exception/insert_exception_tests.cpp index 588a6713..d4c1e243 100644 --- a/test/exception/insert_exception_tests.cpp +++ b/test/exception/insert_exception_tests.cpp @@ -243,6 +243,62 @@ struct insert_test_rehash3 : public insert_test_base #define ALL_TESTS BASIC_TESTS #endif - EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ) + +template +struct pair_emplace_test1 : public insert_test_base +{ + typedef BOOST_DEDUCED_TYPENAME insert_test_base::strong_type strong_type; + + void run(T& x, strong_type& strong) const { + for(BOOST_DEDUCED_TYPENAME test::random_values::const_iterator + it = this->values.begin(), end = this->values.end(); + it != end; ++it) + { + strong.store(x, test::detail::tracker.count_allocations); + x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(it->first), + boost::make_tuple(it->second)); + } + } +}; + +template +struct pair_emplace_test2 : public insert_test_base +{ + typedef BOOST_DEDUCED_TYPENAME insert_test_base::strong_type strong_type; + + void run(T& x, strong_type& strong) const { + for(BOOST_DEDUCED_TYPENAME test::random_values::const_iterator + it = this->values.begin(), end = this->values.end(); + it != end; ++it) + { + strong.store(x, test::detail::tracker.count_allocations); + x.emplace(boost::unordered::piecewise_construct, + boost::make_tuple(it->first), + boost::make_tuple(it->second.tag1_, it->second.tag2_)); + } + } +}; + +EXCEPTION_TESTS((pair_emplace_test1)(pair_emplace_test2), CONTAINER_PAIR_SEQ) + +template +struct index_insert_test1 : public insert_test_base +{ + typedef BOOST_DEDUCED_TYPENAME insert_test_base::strong_type strong_type; + + void run(T& x, strong_type& strong) const { + for(BOOST_DEDUCED_TYPENAME test::random_values::const_iterator + it = this->values.begin(), end = this->values.end(); + it != end; ++it) + { + strong.store(x, test::detail::tracker.count_allocations); + x[it->first]; + } + } +}; + +EXCEPTION_TESTS((index_insert_test1), (test_map)) + RUN_TESTS()