Permalink
Browse files

Fixed a bug with copy constructing a backup holder; changed some tests

  • Loading branch information...
apolukhin committed Dec 12, 2014
1 parent a090e75 commit 6db01d649441e0d16b386bd357a9141b8f3f3b17
Showing with 62 additions and 1 deletion.
  1. +40 −1 include/boost/variant/variant.hpp
  2. +22 −0 test/variant_nonempty_check.cpp
@@ -679,10 +679,48 @@ class backup_assigner
new(addr) RhsT(*static_cast<const RhsT*>(obj));
}
template <typename LhsT>
void backup_assign_impl(
backup_holder<LhsT>& lhs_content
, mpl::false_ // is_nothrow_move_constructible
, long
)
{
// Move lhs content to backup...
backup_holder<LhsT> backup_lhs_content(0);
backup_lhs_content.swap(lhs_content); // nothrow
// ...destroy lhs content...
lhs_content.~backup_holder<LhsT>(); // nothrow
BOOST_TRY
{
// ...and attempt to copy rhs content into lhs storage:
copy_rhs_content_(lhs_.storage_.address(), rhs_content_);
}
BOOST_CATCH (...)
{
// In case of failure, copy backup pointer to lhs storage...
new(lhs_.storage_.address())
backup_holder<LhsT>( 0 ); // nothrow
static_cast<backup_holder<LhsT>* >(lhs_.storage_.address())
->swap(backup_lhs_content); // nothrow
// ...and rethrow:
BOOST_RETHROW;
}
BOOST_CATCH_END
// In case of success, indicate new content type:
lhs_.indicate_which(rhs_which_); // nothrow
}
template <typename LhsT>
void backup_assign_impl(
LhsT& lhs_content
, mpl::true_ // is_nothrow_move_constructible
, int
)
{
// Move lhs content to backup...
@@ -719,6 +757,7 @@ class backup_assigner
void backup_assign_impl(
LhsT& lhs_content
, mpl::false_ // is_nothrow_move_constructible
, int
)
{
// Backup lhs content...
@@ -762,7 +801,7 @@ class backup_assigner
typedef typename is_nothrow_move_constructible<LhsT>::type
nothrow_move;
backup_assign_impl( lhs_content, nothrow_move() );
backup_assign_impl( lhs_content, nothrow_move(), 1L);
BOOST_VARIANT_AUX_RETURN_VOID;
}
@@ -102,6 +102,26 @@ struct nonthrowing_class {
nonthrowing_class() BOOST_NOEXCEPT_IF(false) : trash(123) {
prevent_compiler_noexcept_detection();
}
nonthrowing_class(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class& operator=(const nonthrowing_class&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
nonthrowing_class(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
}
const nonthrowing_class& operator=(nonthrowing_class&&) BOOST_NOEXCEPT_IF(false) {
prevent_compiler_noexcept_detection();
return *this;
}
#endif
};
inline void check_1(int helper = 1)
@@ -243,6 +263,8 @@ inline void check_5(int helper = 1)
BOOST_CHECK(boost::get<throwing_class>(&v1));
}
boost::get<throwing_class>(v1).trash = throwing_class::do_not_throw;
boost::get<throwing_class>(v2).trash = throwing_class::do_not_throw;
v1 = nonthrowing_class();
v2 = nonthrowing_class();
try {

0 comments on commit 6db01d6

Please sign in to comment.