diff --git a/include/boost/variant2/variant.hpp b/include/boost/variant2/variant.hpp index efd33ab..3506524 100644 --- a/include/boost/variant2/variant.hpp +++ b/include/boost/variant2/variant.hpp @@ -335,13 +335,13 @@ template using resolve_overload_index = mp_find struct variant_base_impl; // trivially destructible, single buffered -template using variant_base = variant_base_impl...>, mp_all...>, T...>; +template struct variant_base_impl; // trivially destructible, single buffered +template using variant_base = variant_base_impl...>::value, mp_all...>::value || mp_any...>::value, T...>; struct none {}; // trivially destructible, single buffered -template struct variant_base_impl +template struct variant_base_impl { int ix_; variant_storage st1_; @@ -374,7 +374,9 @@ template struct variant_base_impl template void emplace( A&&... a ) { - size_t const J = I+1; + std::size_t const J = I+1; + + std::size_t const K = mp_find_if, std::is_nothrow_constructible>::value; using U = mp_at_c, I>; @@ -383,8 +385,25 @@ template struct variant_base_impl st1_.emplace( mp_size_t(), std::forward(a)... ); ix_ = J; } + else if( K < sizeof...(T) ) // have nothrow destructible + { + try + { + st1_.emplace( mp_size_t(), std::forward(a)... ); + ix_ = J; + } + catch( ... ) + { + st1_.emplace( mp_size_t() ); + ix_ = K; + + throw; + } + } else { + assert( std::is_nothrow_move_constructible::value ); + U tmp( std::forward(a)... ); st1_.emplace( mp_size_t(), std::move(tmp) ); @@ -394,7 +413,7 @@ template struct variant_base_impl }; // trivially destructible, double buffered -template struct variant_base_impl +template struct variant_base_impl { int ix_; variant_storage st1_; @@ -446,7 +465,7 @@ template struct variant_base_impl }; // not trivially destructible, single buffered -template struct variant_base_impl +template struct variant_base_impl { int ix_; variant_storage st1_; @@ -501,15 +520,34 @@ template struct variant_base_impl { size_t const J = I+1; + std::size_t const K = mp_find_if, std::is_nothrow_constructible>::value; + using U = mp_at_c, I>; if( std::is_nothrow_constructible::value ) { _destroy(); - st1_.emplace( mp_size_t(), std::forward(a)... ); + st1_.emplace( mp_size_t(), std::forward(a)... ); ix_ = J; } + else if( K < sizeof...(T) ) // have nothrow destructible + { + _destroy(); + + try + { + st1_.emplace( mp_size_t(), std::forward(a)... ); + ix_ = J; + } + catch( ... ) + { + st1_.emplace( mp_size_t() ); + ix_ = K; + + throw; + } + } else { assert( std::is_nothrow_move_constructible::value ); @@ -517,15 +555,15 @@ template struct variant_base_impl U tmp( std::forward(a)... ); _destroy(); - st1_.emplace( mp_size_t(), std::move(tmp) ); + st1_.emplace( mp_size_t(), std::move(tmp) ); ix_ = J; } } }; // not trivially destructible, double buffered -template struct variant_base_impl +template struct variant_base_impl { int ix_; variant_storage st1_;