mirror of
https://github.com/boostorg/variant2.git
synced 2025-06-25 12:01:36 +02:00
Compare commits
12 Commits
boost-1.75
...
feature/do
Author | SHA1 | Date | |
---|---|---|---|
3c9f4e56bf | |||
3015e56bcb | |||
7c37053950 | |||
60995edb41 | |||
84a2c175d0 | |||
ea3268feb4 | |||
6de876954a | |||
efc1d5acca | |||
453b00dec8 | |||
c6186e0a95 | |||
24ccee2104 | |||
93b8618e94 |
197
.github/workflows/ci.yml
vendored
Normal file
197
.github/workflows/ci.yml
vendored
Normal file
@ -0,0 +1,197 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- feature/**
|
||||
|
||||
env:
|
||||
UBSAN_OPTIONS: print_stacktrace=1
|
||||
|
||||
jobs:
|
||||
posix:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: gcc-4.8
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-16.04
|
||||
install: g++-4.8
|
||||
- toolset: gcc-4.9
|
||||
cxxstd: "03,11"
|
||||
os: ubuntu-16.04
|
||||
install: g++-4.9
|
||||
- toolset: gcc-5
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-16.04
|
||||
- toolset: gcc-6
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-16.04
|
||||
install: g++-6
|
||||
- toolset: gcc-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
- toolset: gcc-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
- toolset: gcc-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
- toolset: gcc-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-18.04
|
||||
- toolset: clang
|
||||
compiler: clang++-3.5
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.5
|
||||
- toolset: clang
|
||||
compiler: clang++-3.6
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.6
|
||||
- toolset: clang
|
||||
compiler: clang++-3.7
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.7
|
||||
- toolset: clang
|
||||
compiler: clang++-3.8
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.8
|
||||
- toolset: clang
|
||||
compiler: clang++-3.9
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-3.9
|
||||
- toolset: clang
|
||||
compiler: clang++-4.0
|
||||
cxxstd: "03,11,14"
|
||||
os: ubuntu-16.04
|
||||
install: clang-4.0
|
||||
- toolset: clang
|
||||
compiler: clang++-5.0
|
||||
cxxstd: "03,11,14,1z"
|
||||
os: ubuntu-16.04
|
||||
install: clang-5.0
|
||||
- toolset: clang
|
||||
compiler: clang++-6.0
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
- toolset: clang
|
||||
compiler: clang++-7
|
||||
cxxstd: "03,11,14,17"
|
||||
os: ubuntu-18.04
|
||||
install: clang-7
|
||||
- toolset: clang
|
||||
compiler: clang++-8
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-9
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
compiler: clang++-10
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: ubuntu-20.04
|
||||
- toolset: clang
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
os: macos-10.15
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Install packages
|
||||
if: matrix.install
|
||||
run: sudo apt install ${{matrix.install}}
|
||||
|
||||
- name: Setup Boost
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: $GITHUB_REPOSITORY
|
||||
LIBRARY=${GITHUB_REPOSITORY#*/}
|
||||
echo LIBRARY: $LIBRARY
|
||||
echo "LIBRARY=$LIBRARY" >> $GITHUB_ENV
|
||||
echo GITHUB_BASE_REF: $GITHUB_BASE_REF
|
||||
echo GITHUB_REF: $GITHUB_REF
|
||||
REF=${GITHUB_BASE_REF:-$GITHUB_REF}
|
||||
REF=${REF#refs/heads/}
|
||||
echo REF: $REF
|
||||
BOOST_BRANCH=develop && [ "$REF" == "master" ] && BOOST_BRANCH=master || true
|
||||
echo BOOST_BRANCH: $BOOST_BRANCH
|
||||
cd ..
|
||||
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY
|
||||
./bootstrap.sh
|
||||
./b2 -d0 headers
|
||||
|
||||
- name: Create user-config.jam
|
||||
if: matrix.compiler
|
||||
run: |
|
||||
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
cd ../boost-root
|
||||
./b2 -j3 libs/$LIBRARY/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} variant=debug,release
|
||||
|
||||
windows:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- toolset: msvc-14.1
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2016
|
||||
- toolset: msvc-14.2
|
||||
cxxstd: "14,17,latest"
|
||||
addrmd: 32,64
|
||||
os: windows-2019
|
||||
- toolset: gcc
|
||||
cxxstd: "03,11,14,17,2a"
|
||||
addrmd: 64
|
||||
os: windows-2019
|
||||
|
||||
runs-on: ${{matrix.os}}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Boost
|
||||
shell: cmd
|
||||
run: |
|
||||
echo GITHUB_REPOSITORY: %GITHUB_REPOSITORY%
|
||||
for /f %%i in ("%GITHUB_REPOSITORY%") do set LIBRARY=%%~nxi
|
||||
echo LIBRARY: %LIBRARY%
|
||||
echo LIBRARY=%LIBRARY%>>%GITHUB_ENV%
|
||||
echo GITHUB_BASE_REF: %GITHUB_BASE_REF%
|
||||
echo GITHUB_REF: %GITHUB_REF%
|
||||
if "%GITHUB_BASE_REF%" == "" set GITHUB_BASE_REF=%GITHUB_REF%
|
||||
set BOOST_BRANCH=develop
|
||||
for /f %%i in ("%GITHUB_BASE_REF%") do if "%%~nxi" == "master" set BOOST_BRANCH=master
|
||||
echo BOOST_BRANCH: %BOOST_BRANCH%
|
||||
cd ..
|
||||
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
cd boost-root
|
||||
xcopy /s /e /q %GITHUB_WORKSPACE% libs\%LIBRARY%\
|
||||
git submodule update --init tools/boostdep
|
||||
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" %LIBRARY%
|
||||
cmd /c bootstrap
|
||||
b2 -d0 headers
|
||||
|
||||
- name: Run tests
|
||||
shell: cmd
|
||||
run: |
|
||||
cd ../boost-root
|
||||
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release
|
@ -520,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)... )
|
||||
{
|
||||
}
|
||||
|
||||
@ -564,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()
|
||||
{
|
||||
@ -637,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)... )
|
||||
{
|
||||
}
|
||||
|
||||
@ -687,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)... ); }
|
||||
@ -814,21 +814,21 @@ 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;
|
||||
}
|
||||
|
||||
@ -843,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
|
||||
@ -851,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;
|
||||
}
|
||||
|
||||
@ -868,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;
|
||||
}
|
||||
|
||||
@ -884,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;
|
||||
}
|
||||
|
||||
@ -977,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();
|
||||
}
|
||||
};
|
||||
|
||||
@ -1005,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
|
||||
@ -1013,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 )
|
||||
@ -1028,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;
|
||||
}
|
||||
};
|
||||
@ -1036,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 ){
|
||||
@ -1063,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
|
||||
@ -1101,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;
|
||||
}
|
||||
};
|
||||
|
||||
@ -2085,7 +2092,7 @@ template<class R, class F, class V1, class V2> struct visit_L2
|
||||
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit<R>( f2, std::forward<V2>(v2) );
|
||||
return visit<R>( f2, std::forward<V2>(v2) );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -5,10 +5,11 @@
|
||||
"Peter Dimov"
|
||||
],
|
||||
"maintainers": [
|
||||
"Peter Dimov <pdimov -at- pdimov.com>"
|
||||
"Peter Dimov <pdimov -at- gmail.com>"
|
||||
],
|
||||
"description": "A never-valueless, strong guarantee implementation of std::variant.",
|
||||
"category": [
|
||||
"Containers", "Data"
|
||||
]
|
||||
],
|
||||
"cxxstd": "11"
|
||||
}
|
||||
|
@ -115,4 +115,7 @@ run variant_visit_derived.cpp ;
|
||||
|
||||
run variant_many_types.cpp ;
|
||||
|
||||
run variant_visit_r.cpp ;
|
||||
run variant_visit_r.cpp : : :
|
||||
<toolset>gcc,<target-os>windows:<variant>release
|
||||
<toolset>gcc,<target-os>cygwin:<variant>release
|
||||
;
|
||||
|
@ -57,6 +57,60 @@ STATIC_ASSERT( !std::is_nothrow_move_constructible<X2>::value );
|
||||
STATIC_ASSERT( !std::is_nothrow_copy_assignable<X2>::value );
|
||||
STATIC_ASSERT( !std::is_nothrow_move_assignable<X2>::value );
|
||||
|
||||
struct Y1
|
||||
{
|
||||
int v = 1;
|
||||
|
||||
Y1() = default;
|
||||
Y1(Y1 const&) = delete;
|
||||
Y1(Y1&&) = delete;
|
||||
};
|
||||
|
||||
STATIC_ASSERT( !std::is_copy_constructible<Y1>::value );
|
||||
STATIC_ASSERT( !std::is_move_constructible<Y1>::value );
|
||||
|
||||
struct Y2
|
||||
{
|
||||
int v = 2;
|
||||
|
||||
Y2() = default;
|
||||
Y2(Y2 const&) = delete;
|
||||
Y2(Y2&&) = delete;
|
||||
};
|
||||
|
||||
STATIC_ASSERT( !std::is_copy_constructible<Y2>::value );
|
||||
STATIC_ASSERT( !std::is_move_constructible<Y2>::value );
|
||||
|
||||
struct Z1
|
||||
{
|
||||
static int instances;
|
||||
|
||||
int v = 1;
|
||||
|
||||
Z1() { ++instances; }
|
||||
~Z1() { --instances; }
|
||||
|
||||
Z1(Z1 const&) = delete;
|
||||
Z1(Z1&&) = delete;
|
||||
};
|
||||
|
||||
int Z1::instances = 0;
|
||||
|
||||
struct Z2
|
||||
{
|
||||
static int instances;
|
||||
|
||||
int v = 2;
|
||||
|
||||
Z2() { ++instances; }
|
||||
~Z2() { --instances; }
|
||||
|
||||
Z2(Z2 const&) = delete;
|
||||
Z2(Z2&&) = delete;
|
||||
};
|
||||
|
||||
int Z2::instances = 0;
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
@ -177,5 +231,62 @@ int main()
|
||||
BOOST_TEST_EQ( get<0>(v).v, 4 );
|
||||
}
|
||||
|
||||
{
|
||||
variant<Y1, Y2> v;
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
|
||||
v.emplace<0>();
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
|
||||
v.emplace<1>();
|
||||
BOOST_TEST_EQ( v.index(), 1 );
|
||||
BOOST_TEST_EQ( get<1>(v).v, 2 );
|
||||
|
||||
v.emplace<1>();
|
||||
BOOST_TEST_EQ( v.index(), 1 );
|
||||
BOOST_TEST_EQ( get<1>(v).v, 2 );
|
||||
|
||||
v.emplace<0>();
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
}
|
||||
|
||||
{
|
||||
variant<Z1, Z2> v;
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
BOOST_TEST_EQ( Z1::instances, 1 );
|
||||
BOOST_TEST_EQ( Z2::instances, 0 );
|
||||
|
||||
v.emplace<0>();
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
BOOST_TEST_EQ( Z1::instances, 1 );
|
||||
BOOST_TEST_EQ( Z2::instances, 0 );
|
||||
|
||||
v.emplace<1>();
|
||||
BOOST_TEST_EQ( v.index(), 1 );
|
||||
BOOST_TEST_EQ( get<1>(v).v, 2 );
|
||||
BOOST_TEST_EQ( Z1::instances, 0 );
|
||||
BOOST_TEST_EQ( Z2::instances, 1 );
|
||||
|
||||
v.emplace<1>();
|
||||
BOOST_TEST_EQ( v.index(), 1 );
|
||||
BOOST_TEST_EQ( get<1>(v).v, 2 );
|
||||
BOOST_TEST_EQ( Z1::instances, 0 );
|
||||
BOOST_TEST_EQ( Z2::instances, 1 );
|
||||
|
||||
v.emplace<0>();
|
||||
BOOST_TEST_EQ( v.index(), 0 );
|
||||
BOOST_TEST_EQ( get<0>(v).v, 1 );
|
||||
BOOST_TEST_EQ( Z1::instances, 1 );
|
||||
BOOST_TEST_EQ( Z2::instances, 0 );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( Z1::instances, 0 );
|
||||
BOOST_TEST_EQ( Z2::instances, 0 );
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
Reference in New Issue
Block a user