Compare commits

..

6 Commits

Author SHA1 Message Date
Peter Dimov
3c9f4e56bf Fix visit codegen regression when NDEBUG is not defined 2021-01-24 17:27:24 +02:00
Peter Dimov
3015e56bcb GCC bug 63707 has been fixed for GCC 11 2021-01-23 20:36:12 +02:00
Peter Dimov
7c37053950 Merge branch 'develop' into feature/double-opt 2021-01-13 05:06:00 +02:00
Peter Dimov
60995edb41 Remove g++ 4.7 from GHA 2021-01-13 05:01:44 +02:00
Peter Dimov
6de876954a Merge branch 'develop' into feature/double-opt 2021-01-13 02:32:32 +02:00
Peter Dimov
453b00dec8 Use (i+1)*2+j for the internal index in the double-buffered case, to avoid branches 2021-01-13 02:10:12 +02:00
2 changed files with 122 additions and 131 deletions

View File

@@ -17,10 +17,6 @@ jobs:
fail-fast: false
matrix:
include:
- toolset: gcc-4.7
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.7
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-16.04

View File

@@ -504,23 +504,11 @@ using std::is_trivially_move_assignable;
#endif
#if defined( BOOST_LIBSTDCXX_VERSION ) && BOOST_LIBSTDCXX_VERSION < 40800
template<class T> struct is_trivially_destructible: std::has_trivial_destructor<T>
{
};
#else
using std::is_trivially_destructible;
#endif
// variant_storage
template<class D, class... T> union variant_storage_impl;
template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<detail::is_trivially_destructible<T>...>, T...>;
template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<std::is_trivially_destructible<T>...>, T...>;
template<class D> union variant_storage_impl<D>
{
@@ -532,11 +520,11 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T.
T1 first_;
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
{
}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
{
}
@@ -576,18 +564,18 @@ template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, c
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
~variant_storage_impl()
{
@@ -649,11 +637,11 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T..
T1 first_;
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
{
}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
{
}
@@ -699,18 +687,18 @@ template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, c
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
@@ -819,28 +807,28 @@ template<class U, class... T> using resolve_overload_index = mp11::mp_find<mp11:
// variant_base
template<bool is_trivially_destructible, bool is_single_buffered, class... T> struct variant_base_impl;
template<class... T> using variant_base = variant_base_impl<mp11::mp_all<detail::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
template<class... T> using variant_base = variant_base_impl<mp11::mp_all<std::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
struct none {};
// trivially destructible, single buffered
template<class... T> struct variant_base_impl<true, true, T...>
{
int ix_;
variant_storage<none, T...> st1_;
unsigned ix_;
variant_storage<none, T...> st_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): ix_( 0 ), st_( mp11::mp_size_t<0>() )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
}
@@ -855,7 +843,7 @@ template<class... T> struct variant_base_impl<true, true, T...>
assert( ix_ == J );
return st1_.get( mp11::mp_size_t<J>() );
return st_.get( mp11::mp_size_t<J>() );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
@@ -863,14 +851,14 @@ template<class... T> struct variant_base_impl<true, true, T...>
// size_t const J = I+1;
// assert( ix_ == I+1 );
return st1_.get( mp11::mp_size_t<I+1>() );
return st_.get( mp11::mp_size_t<I+1>() );
}
template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
{
static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
st_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J;
}
@@ -880,7 +868,7 @@ template<class... T> struct variant_base_impl<true, true, T...>
U tmp( std::forward<A>(a)... );
st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
ix_ = J;
}
@@ -896,84 +884,78 @@ template<class... T> struct variant_base_impl<true, true, T...>
// trivially destructible, double buffered
template<class... T> struct variant_base_impl<true, false, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st2_;
unsigned ix_;
variant_storage<none, T...> st_[ 2 ];
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): ix_( 0 ), st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( ( I::value + 1 ) * 2 ), st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
::new( &st_[ 0 ] ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = ( I::value + 1 ) * 2;
}
constexpr std::size_t index() const noexcept
{
return ix_ >= 0? ix_ - 1: -ix_ - 1;
return ix_ / 2 - 1;
}
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{
assert( index() == I );
size_t const J = I+1;
assert( ix_ == J || -ix_ == J );
constexpr mp11::mp_size_t<J> j{};
return ix_ >= 0? st1_.get( j ): st2_.get( j );
return st_[ ix_ & 1 ].get( j );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
// assert( index() == I );
// size_t const J = I+1;
// assert( ix_ == J || -ix_ == J );
// constexpr mp_size_t<J> j{};
return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
return st_[ ix_ & 1 ].get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
{
size_t const J = I+1;
if( ix_ >= 0 )
{
st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = -static_cast<int>( J );
}
else
{
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J;
}
unsigned i2 = 1 - ( ix_ & 1 );
st_[ i2 ].emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J * 2 + i2;
}
};
// not trivially destructible, single buffered
template<class... T> struct variant_base_impl<false, true, T...>
{
int ix_;
variant_storage<none, T...> st1_;
unsigned ix_;
variant_storage<none, T...> st_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): ix_( 0 ), st_( mp11::mp_size_t<0>() )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
}
@@ -989,7 +971,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st1_.get( I() ).~U();
this_->st_.get( I() ).~U();
}
};
@@ -1017,7 +999,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
assert( ix_ == J );
return st1_.get( mp11::mp_size_t<J>() );
return st_.get( mp11::mp_size_t<J>() );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
@@ -1025,7 +1007,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
// size_t const J = I+1;
// assert( ix_ == J );
return st1_.get( mp11::mp_size_t<I+1>() );
return st_.get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> void emplace( A&&... a )
@@ -1040,7 +1022,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
_destroy();
st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
ix_ = J;
}
};
@@ -1048,23 +1030,61 @@ template<class... T> struct variant_base_impl<false, true, T...>
// not trivially destructible, double buffered
template<class... T> struct variant_base_impl<false, false, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st2_;
unsigned ix_;
#if defined(__GNUC__) && __GNUC__ < 11 && !defined(__clang__) && !defined(__INTEL_COMPILER)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 :-(
variant_storage<none, T...> st1_, st2_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( ( I::value + 1 ) * 2 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
{
}
BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
{
return i2 == 0? st1_: st2_;
}
constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
{
return i2 == 0? st1_: st2_;
}
#else
variant_storage<none, T...> st_[ 2 ];
constexpr variant_base_impl(): ix_( 0 ), st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( ( I::value + 1 ) * 2 ), st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }
{
}
BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
{
return st_[ i2 ];
}
constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
{
return st_[ i2 ];
}
#endif
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
::new( &storage( 0 ) ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = ( I::value + 1 ) * 2;
}
//[&]( auto I ){
@@ -1075,35 +1095,18 @@ template<class... T> struct variant_base_impl<false, false, T...>
struct _destroy_L1
{
variant_base_impl * this_;
unsigned i2_;
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st1_.get( I() ).~U();
}
};
struct _destroy_L2
{
variant_base_impl * this_;
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st2_.get( I() ).~U();
this_->storage( i2_ ).get( I() ).~U();
}
};
void _destroy() noexcept
{
if( ix_ > 0 )
{
mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
}
else if( ix_ < 0 )
{
mp11::mp_with_index<1 + sizeof...(T)>( -ix_, _destroy_L2{ this } );
}
mp11::mp_with_index<1 + sizeof...(T)>( ix_ / 2, _destroy_L1{ this, ix_ & 1 } );
}
~variant_base_impl() noexcept
@@ -1113,46 +1116,38 @@ template<class... T> struct variant_base_impl<false, false, T...>
constexpr std::size_t index() const noexcept
{
return ix_ >= 0? ix_ - 1: -ix_ - 1;
return ix_ / 2 - 1;
}
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{
assert( index() == I );
size_t const J = I+1;
assert( ix_ == J || -ix_ == J );
constexpr mp11::mp_size_t<J> j{};
return ix_ >= 0? st1_.get( j ): st2_.get( j );
return storage( ix_ & 1 ).get( j );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
// assert( index() == I );
// size_t const J = I+1;
// assert( ix_ == J || -ix_ == J );
// constexpr mp_size_t<J> j{};
return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
return storage( ix_ & 1 ).get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> void emplace( A&&... a )
{
size_t const J = I+1;
if( ix_ >= 0 )
{
st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
_destroy();
unsigned i2 = 1 - ( ix_ & 1 );
ix_ = -static_cast<int>( J );
}
else
{
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
_destroy();
storage( i2 ).emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
_destroy();
ix_ = J;
}
ix_ = J * 2 + i2;
}
};
@@ -1329,7 +1324,7 @@ template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct v
template<class... T> using variant_ca_base = variant_ca_base_impl<
mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>::value,
mp11::mp_all<detail::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>::value,
T...>;
template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
@@ -1478,7 +1473,7 @@ template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct v
template<class... T> using variant_ma_base = variant_ma_base_impl<
mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>::value,
mp11::mp_all<detail::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>::value,
T...>;
template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>