Fix exception safety when constructing pairs

This commit is contained in:
Daniel James 2017-01-01 18:35:50 +00:00
parent e416cafd49
commit 57cc6d4bac
3 changed files with 118 additions and 14 deletions

View File

@ -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>(a1));
boost::unordered::detail::func::construct_from_tuple(alloc,
boost::unordered::detail::func::const_cast_pointer(
boost::addressof(address->second)),
boost::forward<A2>(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>(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<Key>(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<Key>(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<Mapped>(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<Mapped>(m));
boost::addressof(a.node_->value_ptr()->first)));
BOOST_RETHROW;
}
BOOST_CATCH_END
return a.release();
}
}}}}

View File

@ -31,5 +31,17 @@ typedef boost::unordered_multimap<
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> > test_multimap;
typedef boost::unordered_set<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator<test::exception::object> > test_pair_set;
typedef boost::unordered_multiset<
std::pair<test::exception::object, test::exception::object>,
test::exception::hash,
test::exception::equal_to,
test::exception::allocator2<test::exception::object> > 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)

View File

@ -243,6 +243,62 @@ struct insert_test_rehash3 : public insert_test_base<T>
#define ALL_TESTS BASIC_TESTS
#endif
EXCEPTION_TESTS(ALL_TESTS, CONTAINER_SEQ)
template <class T>
struct pair_emplace_test1 : public insert_test_base<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::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 <class T>
struct pair_emplace_test2 : public insert_test_base<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::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 <class T>
struct index_insert_test1 : public insert_test_base<T>
{
typedef BOOST_DEDUCED_TYPENAME insert_test_base<T>::strong_type strong_type;
void run(T& x, strong_type& strong) const {
for(BOOST_DEDUCED_TYPENAME test::random_values<T>::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()