Compare commits

...

28 Commits

Author SHA1 Message Date
Peter Dimov
a3d35e61fe g++ 4.7 doesn't have std::is_trivially_destructible 2021-01-13 04:51:27 +02:00
Peter Dimov
84a2c175d0 Use variant=release for variant_visit_r under g++/windows 2021-01-13 04:44:56 +02:00
Peter Dimov
ea3268feb4 Add .github/workflows 2021-01-13 04:19:15 +02:00
Peter Dimov
efc1d5acca Add more tests to variant_emplace_index.cpp 2021-01-13 02:32:05 +02:00
Peter Dimov
c6186e0a95 Merge pull request #22 from eldiener/develop
Add "cxxstd" json field. The "cxxstd" json field is being added to ea…
2020-12-16 18:45:01 +02:00
Edward Diener
24ccee2104 Add "cxxstd" json field. The "cxxstd" json field is being added to each Boost library's meta json information for libraries whose minumum C++ standard compilation level is C++11 on up. The value of this field matches one of the values for 'cxxstd' in Boost.Build. The purpose of doing this is to provide information for the Boost website documentation for each library which will specify the minimum C++ standard compilation that an end-user must employ in order to use the particular library. This will aid end-users who want to know if they can successfully use a Boost library based on their C++ compiler's compilation level, without having to search the library's documentation to find this out. 2020-12-16 01:45:24 -05:00
Peter Dimov
93b8618e94 Update maintainer e-mail 2020-12-12 01:08:09 +02:00
Peter Dimov
1ebc29aa02 Remove boost_install call from CMakeLists.txt 2020-06-11 17:21:57 +03:00
Peter Dimov
d3db874762 Document visit<R> 2020-06-03 18:01:57 +03:00
Peter Dimov
5586ebaa64 Add support for visit<R> 2020-06-03 17:00:13 +03:00
Peter Dimov
bede3777a8 Add test for nullary visit 2020-06-03 14:29:24 +03:00
Peter Dimov
b302dd5912 Update changelog 2020-05-22 17:57:29 +03:00
Peter Dimov
2ad6fed07a Update revision history 2020-05-10 19:34:12 +03:00
Peter Dimov
84ea994325 Add specialization for variant_storage_impl<mp_false, ...> 2020-05-09 19:56:27 +03:00
Peter Dimov
465e5bac3d Add specialization for variant_storage_impl<mp_true, ...> to reduce instantiations 2020-05-09 18:14:12 +03:00
Peter Dimov
41829b0fb1 test/variant_many_types: cosmetic fixes 2020-05-09 17:55:42 +03:00
Peter Dimov
b57d75ff80 Merge branch 'develop' into feature/many-types 2020-05-09 14:41:29 +03:00
Peter Dimov
03019860df Fix gcc-10 version check 2020-05-09 05:10:28 +03:00
Peter Dimov
8ec4720d2d Merge branch 'feature/clang-10' into feature/gcc-10 2020-05-09 05:09:11 +03:00
Peter Dimov
75f574fc48 Move warning suppression before the includes 2020-05-09 04:42:27 +03:00
Peter Dimov
1d79adfca0 Add gcc-10 to Travis 2020-05-09 04:32:11 +03:00
Peter Dimov
fa92e40b35 Disable failing constexpr tests on g++ 10.1 2020-05-09 04:31:26 +03:00
Peter Dimov
a403f82691 Disable -Wdeprecated-volatile 2020-05-09 03:57:27 +03:00
Peter Dimov
a7d0da59ad Add clang-10 to Travis 2020-05-09 03:50:20 +03:00
Peter Dimov
fa872cb835 test/variant_many_types: add a constructor to Y 2020-05-08 23:23:19 +03:00
Peter Dimov
93204676f5 Add test/variant_many_types 2020-05-08 22:22:49 +03:00
Peter Dimov
772ef0d312 Support derived types in visit 2020-05-06 20:11:03 +03:00
Peter Dimov
f3b3b533aa Remove local mp_power_set implementation, as it's now in mp11 2020-03-20 02:26:01 +02:00
19 changed files with 917 additions and 89 deletions

201
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,201 @@
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.7
cxxstd: "03,11"
os: ubuntu-16.04
install: g++-4.7
- 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

View File

@@ -92,6 +92,17 @@ matrix:
sources:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: g++-10
env: TOOLSET=gcc COMPILER=g++-10 CXXSTD=11,14,17,2a
addons:
apt:
packages:
- g++-10
sources:
- ubuntu-toolchain-r-test
- os: linux
compiler: g++-8
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
@@ -223,6 +234,19 @@ matrix:
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: xenial
compiler: clang++-10
env: TOOLSET=clang COMPILER=clang++-10 CXXSTD=11,14,17,2a
addons:
apt:
packages:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
compiler: clang++-8
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-8 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
@@ -284,6 +308,7 @@ matrix:
- os: linux
env: CMAKE_INSTALL_TEST=1
script:
- pip install --user cmake
- mkdir __build__ && cd __build__
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=variant2 -DCMAKE_INSTALL_PREFIX=~/.local ..
- cmake --build . --target install

View File

@@ -17,13 +17,6 @@ target_link_libraries(boost_variant2
Boost::mp11
)
if(BOOST_SUPERPROJECT_VERSION)
include(BoostInstall)
boost_install(TARGETS boost_variant2 HEADER_DIRECTORY include/)
endif()
if(BUILD_TESTING)
add_subdirectory(test)

View File

@@ -11,6 +11,12 @@ http://www.boost.org/LICENSE_1_0.txt
# Revision History
:idprefix: changelog_
## Changes in 1.74.0
* Added support for derived types in `visit`
* Improved compilation performance for many (hundreds of) alternatives.
* Added support for `visit<R>`
## Changes in 1.73.0
* Added support for `std::hash`, `boost::hash`.

View File

@@ -134,7 +134,7 @@ template<class... T>
// visit
template<class F, class... V>
template<class R = /*unspecified*/, class F, class... V>
constexpr /*see below*/ visit(F&& f, V&&... v);
// monostate
@@ -838,7 +838,7 @@ Returns: ::
### visit
```
template<class F, class... V>
template<class R = /*unspecified*/, class F, class... V>
constexpr /*see below*/ visit(F&& f, V&&... v);
```
[none]
@@ -846,6 +846,10 @@ template<class F, class... V>
+
Returns: :: `std::forward<F>(f)(get<I>(std::forward<V>(v))...)`, where
`I...` is `v.index()...`.
Remarks: :: If `R` is given explicitly, as in `visit<int>`, the return
type is `R`. Otherwise, it's deduced from `F`. All possible applications
of `F` to the variant alternatives must have the same return type for
this deduction to succeed.
### swap

View File

@@ -504,11 +504,23 @@ 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<std::is_trivially_destructible<T>...>, T...>;
template<class... T> using variant_storage = variant_storage_impl<mp11::mp_all<detail::is_trivially_destructible<T>...>, T...>;
template<class D> union variant_storage_impl<D>
{
@@ -549,6 +561,88 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T.
template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
};
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_false, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
{
T0 t0_;
T1 t1_;
T2 t2_;
T3 t3_;
T4 t4_;
T5 t5_;
T6 t6_;
T7 t7_;
T8 t8_;
T9 t9_;
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<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)... ) {}
~variant_storage_impl()
{
}
template<class... A> void emplace( mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
template<class... A> void emplace( mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
template<std::size_t I, class... A> void emplace( mp11::mp_size_t<I>, A&&... a )
{
rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
}
BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
};
// all trivially destructible
template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T...>
{
@@ -590,6 +684,105 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T..
template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-1> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-1>() ); }
};
template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class... T> union variant_storage_impl<mp11::mp_true, T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T...>
{
T0 t0_;
T1 t1_;
T2 t2_;
T3 t3_;
T4 t4_;
T5 t5_;
T6 t6_;
T7 t7_;
T8 t8_;
T9 t9_;
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<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<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)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<2>, A&&... a ) { ::new( &t2_ ) T2( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<3>, A&&... a ) { ::new( &t3_ ) T3( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<4>, A&&... a ) { ::new( &t4_ ) T4( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<5>, A&&... a ) { ::new( &t5_ ) T5( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<6>, A&&... a ) { ::new( &t6_ ) T6( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<7>, A&&... a ) { ::new( &t7_ ) T7( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<8>, A&&... a ) { ::new( &t8_ ) T8( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<9>, A&&... a ) { ::new( &t9_ ) T9( std::forward<A>(a)... ); }
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_false, mp11::mp_size_t<I>, A&&... a )
{
rest_.emplace( mp11::mp_size_t<I-10>(), std::forward<A>(a)... );
}
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, A&&... a )
{
*this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
}
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
{
this->emplace_impl( mp11::mp_all<
detail::is_trivially_move_assignable<T0>,
detail::is_trivially_move_assignable<T1>,
detail::is_trivially_move_assignable<T2>,
detail::is_trivially_move_assignable<T3>,
detail::is_trivially_move_assignable<T4>,
detail::is_trivially_move_assignable<T5>,
detail::is_trivially_move_assignable<T6>,
detail::is_trivially_move_assignable<T7>,
detail::is_trivially_move_assignable<T8>,
detail::is_trivially_move_assignable<T9>,
detail::is_trivially_move_assignable<T>...>(), mp11::mp_size_t<I>(), std::forward<A>(a)... );
}
BOOST_CXX14_CONSTEXPR T0& get( mp11::mp_size_t<0> ) noexcept { return t0_; }
constexpr T0 const& get( mp11::mp_size_t<0> ) const noexcept { return t0_; }
BOOST_CXX14_CONSTEXPR T1& get( mp11::mp_size_t<1> ) noexcept { return t1_; }
constexpr T1 const& get( mp11::mp_size_t<1> ) const noexcept { return t1_; }
BOOST_CXX14_CONSTEXPR T2& get( mp11::mp_size_t<2> ) noexcept { return t2_; }
constexpr T2 const& get( mp11::mp_size_t<2> ) const noexcept { return t2_; }
BOOST_CXX14_CONSTEXPR T3& get( mp11::mp_size_t<3> ) noexcept { return t3_; }
constexpr T3 const& get( mp11::mp_size_t<3> ) const noexcept { return t3_; }
BOOST_CXX14_CONSTEXPR T4& get( mp11::mp_size_t<4> ) noexcept { return t4_; }
constexpr T4 const& get( mp11::mp_size_t<4> ) const noexcept { return t4_; }
BOOST_CXX14_CONSTEXPR T5& get( mp11::mp_size_t<5> ) noexcept { return t5_; }
constexpr T5 const& get( mp11::mp_size_t<5> ) const noexcept { return t5_; }
BOOST_CXX14_CONSTEXPR T6& get( mp11::mp_size_t<6> ) noexcept { return t6_; }
constexpr T6 const& get( mp11::mp_size_t<6> ) const noexcept { return t6_; }
BOOST_CXX14_CONSTEXPR T7& get( mp11::mp_size_t<7> ) noexcept { return t7_; }
constexpr T7 const& get( mp11::mp_size_t<7> ) const noexcept { return t7_; }
BOOST_CXX14_CONSTEXPR T8& get( mp11::mp_size_t<8> ) noexcept { return t8_; }
constexpr T8 const& get( mp11::mp_size_t<8> ) const noexcept { return t8_; }
BOOST_CXX14_CONSTEXPR T9& get( mp11::mp_size_t<9> ) noexcept { return t9_; }
constexpr T9 const& get( mp11::mp_size_t<9> ) const noexcept { return t9_; }
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<mp11::mp_list<T...>, I-10>& get( mp11::mp_size_t<I> ) noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
template<std::size_t I> constexpr mp11::mp_at_c<mp11::mp_list<T...>, I-10> const& get( mp11::mp_size_t<I> ) const noexcept { return rest_.get( mp11::mp_size_t<I-10>() ); }
};
// resolve_overload_*
template<class... T> struct overload;
@@ -626,7 +819,7 @@ 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<std::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<detail::is_trivially_destructible<T>...>::value, mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value, T...>;
struct none {};
@@ -1136,7 +1329,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<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_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,
T...>;
template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
@@ -1285,7 +1478,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<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_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,
T...>;
template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
@@ -1768,6 +1961,25 @@ namespace detail
template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template<class... T> variant<T...> const & extract_variant_base_( variant<T...> const & );
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
template<class V> struct extract_vbase_impl
{
using type = decltype( extract_variant_base_( std::declval<V>() ) );
};
template<class V> using extract_variant_base = remove_cv_ref_t< typename extract_vbase_impl<V>::type >;
#else
template<class V> using extract_variant_base = remove_cv_ref_t< decltype( extract_variant_base_( std::declval<V>() ) ) >;
#endif
template<class V> using variant_base_size = variant_size< extract_variant_base<V> >;
template<class T, class U> struct copy_cv_ref
{
using type = T;
@@ -1807,13 +2019,28 @@ template<class F> struct Qret
template<class L> using front_if_same = mp11::mp_if<mp11::mp_apply<mp11::mp_same, L>, mp11::mp_front<L>>;
template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, remove_cv_ref_t<V>, mp11::mp_list<V>>;
template<class V> using apply_cv_ref = mp11::mp_product<copy_cv_ref_t, extract_variant_base<V>, mp11::mp_list<V>>;
template<class F, class... V> using Vret = front_if_same<mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...>>;
struct deduced {};
#if !BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
template<class R, class F, class... V> using Vret = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
#else
template<class R, class F, class... V> struct Vret_impl
{
using type = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_product_q<Qret<F>, apply_cv_ref<V>...> >;
};
template<class R, class F, class... V> using Vret = typename Vret_impl<R, F, V...>::type;
#endif
} // namespace detail
template<class F> constexpr auto visit( F&& f ) -> decltype(std::forward<F>(f)())
template<class R = detail::deduced, class F> constexpr auto visit( F&& f ) -> detail::Vret<R, F>
{
return std::forward<F>(f)();
}
@@ -1821,12 +2048,12 @@ template<class F> constexpr auto visit( F&& f ) -> decltype(std::forward<F>(f)()
namespace detail
{
template<class F, class V1> struct visit_L1
template<class R, class F, class V1> struct visit_L1
{
F&& f;
V1&& v1;
template<class I> auto operator()( I ) const -> Vret<F, V1>
template<class I> auto operator()( I ) const -> Vret<R, F, V1>
{
return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
}
@@ -1834,9 +2061,9 @@ template<class F, class V1> struct visit_L1
} // namespace detail
template<class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<F, V1>
template<class R = detail::deduced, class F, class V1> constexpr auto visit( F&& f, V1&& v1 ) -> detail::Vret<R, F, V1>
{
return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L1<F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L1<R, F, V1>{ std::forward<F>(f), std::forward<V1>(v1) } );
}
#if defined(BOOST_NO_CXX14_GENERIC_LAMBDAS) || BOOST_WORKAROUND( BOOST_MSVC, < 1920 )
@@ -1860,31 +2087,31 @@ template<class F, class A> bind_front_<F, A> bind_front( F&& f, A&& a )
return bind_front_<F, A>{ std::forward<F>(f), std::forward<A>(a) };
}
template<class F, class V1, class V2> struct visit_L2
template<class R, class F, class V1, class V2> struct visit_L2
{
F&& f;
V1&& v1;
V2&& v2;
template<class I> auto operator()( I ) const -> Vret<F, V1, V2>
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( f2, std::forward<V2>(v2) );
return visit<R>( f2, std::forward<V2>(v2) );
}
};
} // namespace detail
template<class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<F, V1, V2>
template<class R = detail::deduced, class F, class V1, class V2> constexpr auto visit( F&& f, V1&& v1, V2&& v2 ) -> detail::Vret<R, F, V1, V2>
{
return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L2<F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L2<R, F, V1, V2>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2) } );
}
namespace detail
{
template<class F, class V1, class V2, class V3> struct visit_L3
template<class R, class F, class V1, class V2, class V3> struct visit_L3
{
F&& f;
@@ -1892,24 +2119,24 @@ template<class F, class V1, class V2, class V3> struct visit_L3
V2&& v2;
V3&& v3;
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3>
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3>
{
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
}
};
} // namespace detail
template<class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<F, V1, V2, V3>
template<class R = detail::deduced, class F, class V1, class V2, class V3> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3 ) -> detail::Vret<R, F, V1, V2, V3>
{
return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L3<F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L3<R, F, V1, V2, V3>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3) } );
}
namespace detail
{
template<class F, class V1, class V2, class V3, class V4> struct visit_L4
template<class R, class F, class V1, class V2, class V3, class V4> struct visit_L4
{
F&& f;
@@ -1918,28 +2145,28 @@ template<class F, class V1, class V2, class V3, class V4> struct visit_L4
V3&& v3;
V4&& v4;
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3, V4>
template<class I> auto operator()( I ) const -> Vret<R, F, V1, V2, V3, V4>
{
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
return visit<R>( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
}
};
} // namespace detail
template<class F, class V1, class V2, class V3, class V4> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> detail::Vret<F, V1, V2, V3, V4>
template<class R = detail::deduced, class F, class V1, class V2, class V3, class V4> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V3&& v3, V4&& v4 ) -> detail::Vret<R, F, V1, V2, V3, V4>
{
return mp11::mp_with_index<variant_size<V1>>( v1.index(), detail::visit_L4<F, V1, V2, V3, V4>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) } );
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), detail::visit_L4<R, F, V1, V2, V3, V4>{ std::forward<F>(f), std::forward<V1>(v1), std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) } );
}
#else
template<class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<F, V1, V2, V...>
template<class R = detail::deduced, class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V1&& v1, V2&& v2, V&&... v ) -> detail::Vret<R, F, V1, V2, V...>
{
return mp11::mp_with_index<variant_size<V1>>( v1.index(), [&]( auto I ){
return mp11::mp_with_index<detail::variant_base_size<V1>>( v1.index(), [&]( auto I ){
auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
return visit( f2, std::forward<V2>(v2), std::forward<V>(v)... );
return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
});
}

View File

@@ -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"
}

View File

@@ -110,3 +110,12 @@ run variant_hash.cpp ;
run variant_trivial.cpp ;
run variant_special.cpp ;
run variant_visit_derived.cpp ;
run variant_many_types.cpp ;
run variant_visit_r.cpp : : :
<toolset>gcc,<target-os>windows:<variant>release
<toolset>gcc,<target-os>cygwin:<variant>release
;

View File

@@ -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();
}

View File

@@ -6,6 +6,12 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#if defined( __clang__ ) && defined( __has_warning )
# if __has_warning( "-Wdeprecated-volatile" )
# pragma clang diagnostic ignored "-Wdeprecated-volatile"
# endif
#endif
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>

View File

@@ -6,6 +6,12 @@
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#if defined( __clang__ ) && defined( __has_warning )
# if __has_warning( "-Wdeprecated-volatile" )
# pragma clang diagnostic ignored "-Wdeprecated-volatile"
# endif
#endif
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>

View File

@@ -7,11 +7,8 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
#include <utility>
#include <string>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
using namespace boost::variant2;
@@ -108,9 +105,17 @@ int main()
STATIC_ASSERT( v.index() == 4 );
}
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 100200)
// no idea why this fails on g++ 10
#else
{
constexpr variant<int, int, float, float, X, X> v( in_place_index_t<5>{}, 0, 0 );
STATIC_ASSERT( v.index() == 5 );
}
#endif
}

View File

@@ -7,6 +7,8 @@
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
using namespace boost::variant2;
@@ -100,6 +102,12 @@ int main()
STATIC_ASSERT( holds_alternative<X>(v) );
}
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 100200)
// no idea why this fails on g++ 10
#else
{
constexpr variant<int, int, float, float, X> v( in_place_type_t<X>{}, 0, 0 );
@@ -107,4 +115,6 @@ int main()
STATIC_ASSERT( holds_alternative<X>(v) );
}
#endif
}

109
test/variant_many_types.cpp Normal file
View File

@@ -0,0 +1,109 @@
// Copyright 2020 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning( disable: 4503 ) // decorated name length exceeded
#endif
#include <boost/variant2/variant.hpp>
#include <boost/mp11.hpp>
#include <boost/core/lightweight_test.hpp>
using namespace boost::mp11;
template<class I> struct X
{
static int const value = I::value;
int v_;
};
template<class I> int const X<I>::value;
template<class I> struct Y
{
static int const value = I::value;
int v_;
Y() = default;
Y( Y const& ) = default;
explicit Y( int v ): v_( v ) {}
Y& operator=( Y const& ) noexcept = default;
Y& operator=( Y&& r ) noexcept
{
v_ = r.v_;
return *this;
}
};
template<class I> int const Y<I>::value;
template<class I> struct Z
{
static int const value = I::value;
int v_;
~Z() {}
};
template<class I> int const Z<I>::value;
template<class V> struct F1
{
template<class T> void operator()( T ) const
{
int const i = T::value;
T t{ i * 2 };
using boost::variant2::get;
{
V v( t );
BOOST_TEST_EQ( v.index(), i );
BOOST_TEST_EQ( get<i>( v ).v_, t.v_ );
BOOST_TEST_EQ( get<T>( v ).v_, t.v_ );
}
{
V const v( t );
BOOST_TEST_EQ( v.index(), i );
BOOST_TEST_EQ( get<i>( v ).v_, t.v_ );
BOOST_TEST_EQ( get<T>( v ).v_, t.v_ );
}
{
V v;
v = t;
BOOST_TEST_EQ( v.index(), i );
BOOST_TEST_EQ( get<i>( v ).v_, t.v_ );
BOOST_TEST_EQ( get<T>( v ).v_, t.v_ );
}
}
};
template<class V> void test()
{
mp_for_each<V>( F1<V>() );
}
int main()
{
int const N = 32;
using V = mp_rename<mp_iota_c<N>, boost::variant2::variant>;
test< mp_transform<X, V> >();
test< mp_transform<Y, V> >();
test< mp_transform<Z, V> >();
return boost::report_errors();
}

View File

@@ -14,28 +14,6 @@
#include <boost/mp11.hpp>
using namespace boost::mp11;
// mp_power_set<L>
template<class L> struct mp_power_set_impl;
template<class L> using mp_power_set = typename mp_power_set_impl<L>::type;
template<template<class...> class L> struct mp_power_set_impl< L<> >
{
using type = L< L<> >;
};
template<template<class...> class L, class T1, class... T> struct mp_power_set_impl< L<T1, T...> >
{
using S1 = mp_power_set< L<T...> >;
template<class L2> using _f = mp_push_front<L2, T1>;
using S2 = mp_transform<_f, S1>;
using type = mp_append< S1, S2 >;
};
//
using namespace boost::variant2;

View File

@@ -14,28 +14,6 @@
#include <boost/mp11.hpp>
using namespace boost::mp11;
// mp_power_set<L>
template<class L> struct mp_power_set_impl;
template<class L> using mp_power_set = typename mp_power_set_impl<L>::type;
template<template<class...> class L> struct mp_power_set_impl< L<> >
{
using type = L< L<> >;
};
template<template<class...> class L, class T1, class... T> struct mp_power_set_impl< L<T1, T...> >
{
using S1 = mp_power_set< L<T...> >;
template<class L2> using _f = mp_push_front<L2, T1>;
using S2 = mp_transform<_f, S1>;
using type = mp_append< S1, S2 >;
};
//
struct D

View File

@@ -37,6 +37,10 @@ struct F
int main()
{
{
BOOST_TEST_EQ( (visit( []{ return 5; } )), 5 );
}
{
variant<int> v( 1 );

View File

@@ -0,0 +1,57 @@
// Copyright 2017, 2020 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data
#endif
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/config.hpp>
#include <boost/config/workaround.hpp>
#include <utility>
struct X: boost::variant2::variant<int, float>
{
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
template<class T> explicit X( T&& t ): variant( std::forward<T>( t ) ) {};
#else
using variant::variant;
#endif
};
template<class... T> struct Y: boost::variant2::variant<T...>
{
using boost::variant2::variant<T...>::variant;
};
int main()
{
{
X v1( 1 );
X const v2( 3.14f );
BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 );
visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 );
visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) );
}
{
Y<int, float> v1( 1 );
Y<int, float> const v2( 3.14f );
BOOST_TEST_EQ( (visit( []( int x1, float x2 ){ return (int)(x1 * 1000) + (int)(x2 * 100); }, v1, v2 )), 1314 );
visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, v1, v2 );
visit( []( int x1, float x2 ){ BOOST_TEST_EQ( x1, 1 ); BOOST_TEST_EQ( x2, 3.14f ); }, std::move(v1), std::move(v2) );
}
return boost::report_errors();
}

98
test/variant_visit_r.cpp Normal file
View File

@@ -0,0 +1,98 @@
// Copyright 2017 Peter Dimov.
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#if defined(_MSC_VER)
# pragma warning( disable: 4244 ) // conversion from float to int, possible loss of data
#endif
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
using namespace boost::variant2;
struct F1
{
template<class T1> T1 operator()( T1 t1 ) const
{
return t1;
}
};
struct F2
{
template<class T1, class T2> auto operator()( T1 t1, T2 t2 ) const -> decltype( t1 + t2 )
{
return t1 + t2;
}
};
struct F3
{
template<class T1, class T2, class T3> auto operator()( T1 t1, T2 t2, T3 t3 ) const -> decltype( t1 + t2 + t3 )
{
return t1 + t2 + t3;
}
};
struct F4
{
template<class T1, class T2, class T3, class T4> auto operator()( T1 t1, T2 t2, T3 t3, T4 t4 ) const -> decltype( t1 + t2 + t3 + t4 )
{
return t1 + t2 + t3 + t4;
}
};
int main()
{
{
BOOST_TEST_EQ( (visit<int>( []{ return 3.14f; } )), 3 );
}
{
variant<int, float> v( 1 );
BOOST_TEST_EQ( visit<int>( F1(), v ), 1 );
BOOST_TEST_EQ( visit<float>( F1(), v ), 1.0f );
}
{
variant<int, float> const v( 3.14f );
BOOST_TEST_EQ( visit<int>( F1(), v ), 3 );
BOOST_TEST_EQ( visit<float>( F1(), v ), 3.14f );
}
{
variant<int, float> v1( 1 );
variant<int, float> const v2( 3.14f );
BOOST_TEST_EQ( visit<int>( F2(), v1, v2 ), 4 );
BOOST_TEST_EQ( visit<float>( F2(), v1, v2 ), 1 + 3.14f );
}
{
variant<int, float, double> v1( 1 );
variant<int, float, double> const v2( 3.14f );
variant<int, float, double> v3( 6.28 );
BOOST_TEST_EQ( visit<int>( F3(), v1, v2, v3 ), 10 );
BOOST_TEST_EQ( visit<float>( F3(), v1, v2, v3 ), static_cast<float>( 1 + 3.14f + 6.28 ) );
}
{
variant<int, float, double, char> v1( 1 );
variant<int, float, double, char> const v2( 3.14f );
variant<int, float, double, char> v3( 6.28 );
variant<int, float, double, char> const v4( 'A' );
BOOST_TEST_EQ( visit<int>( F4(), v1, v2, v3, v4 ), 10 + 'A' );
BOOST_TEST_EQ( visit<float>( F4(), v1, v2, v3, v4 ), static_cast<float>( 1 + 3.14f + 6.28 + 'A' ) );
}
return boost::report_errors();
}