mirror of
https://github.com/boostorg/variant2.git
synced 2025-12-23 07:12:33 +01:00
Compare commits
57 Commits
feature/ad
...
feature/gc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3d35e61fe | ||
|
|
84a2c175d0 | ||
|
|
ea3268feb4 | ||
|
|
efc1d5acca | ||
|
|
c6186e0a95 | ||
|
|
24ccee2104 | ||
|
|
93b8618e94 | ||
|
|
1ebc29aa02 | ||
|
|
d3db874762 | ||
|
|
5586ebaa64 | ||
|
|
bede3777a8 | ||
|
|
b302dd5912 | ||
|
|
2ad6fed07a | ||
|
|
84ea994325 | ||
|
|
465e5bac3d | ||
|
|
41829b0fb1 | ||
|
|
b57d75ff80 | ||
|
|
03019860df | ||
|
|
8ec4720d2d | ||
|
|
75f574fc48 | ||
|
|
1d79adfca0 | ||
|
|
fa92e40b35 | ||
|
|
a403f82691 | ||
|
|
a7d0da59ad | ||
|
|
fa872cb835 | ||
|
|
93204676f5 | ||
|
|
772ef0d312 | ||
|
|
f3b3b533aa | ||
|
|
4b60dee4b6 | ||
|
|
76c67c9b21 | ||
|
|
308bd731a5 | ||
|
|
719c43316f | ||
|
|
d6680df4e5 | ||
|
|
8cf72527a6 | ||
|
|
b649a39776 | ||
|
|
37f6efab5d | ||
|
|
5259bdd5fc | ||
|
|
9964e77dd2 | ||
|
|
57ab36bd95 | ||
|
|
fac5992e45 | ||
|
|
972280e59f | ||
|
|
ef2ef292b9 | ||
|
|
3b2fb1a48a | ||
|
|
4f81882bfd | ||
|
|
17bc06b090 | ||
|
|
c4cad3e96a | ||
|
|
83ff667813 | ||
|
|
5e76451843 | ||
|
|
c2b5d101eb | ||
|
|
a92185a86d | ||
|
|
a795f9cf01 | ||
|
|
f6e2e78d7d | ||
|
|
1f05cdfb17 | ||
|
|
1203aa97c0 | ||
|
|
b3229d48b7 | ||
|
|
be11d94adc | ||
|
|
fece11142c |
201
.github/workflows/ci.yml
vendored
Normal file
201
.github/workflows/ci.yml
vendored
Normal 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
|
||||
45
.travis.yml
45
.travis.yml
@@ -4,8 +4,6 @@
|
||||
|
||||
language: cpp
|
||||
|
||||
sudo: false
|
||||
|
||||
dist: xenial
|
||||
|
||||
branches:
|
||||
@@ -25,8 +23,14 @@ matrix:
|
||||
|
||||
include:
|
||||
- os: linux
|
||||
compiler: g++
|
||||
env: TOOLSET=gcc COMPILER=g++ CXXSTD=11
|
||||
compiler: g++-4.8
|
||||
env: TOOLSET=gcc COMPILER=g++-4.8 CXXSTD=11
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- g++-4.8
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
compiler: g++-4.9
|
||||
@@ -88,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
|
||||
@@ -98,6 +113,11 @@ matrix:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
|
||||
- os: linux
|
||||
dist: trusty
|
||||
compiler: clang++
|
||||
env: DIST=trusty TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-3.5
|
||||
env: TOOLSET=clang COMPILER=clang++-3.5 CXXSTD=11,14,1z
|
||||
@@ -214,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
|
||||
@@ -259,7 +292,6 @@ matrix:
|
||||
- ctest --output-on-failure -R boost_variant2
|
||||
|
||||
- os: linux
|
||||
compiler: g++
|
||||
env: CMAKE_SUBDIR_TEST=1
|
||||
install:
|
||||
- BOOST_BRANCH=develop && [ "$TRAVIS_BRANCH" == "master" ] && BOOST_BRANCH=master || true
|
||||
@@ -276,8 +308,9 @@ 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;config;mp11" -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=variant2 -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
- cmake --build . --target install
|
||||
- cd ../libs/variant2/test/cmake_install_test && mkdir __build__ && cd __build__
|
||||
- cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
|
||||
|
||||
@@ -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)
|
||||
|
||||
14
appveyor.yml
14
appveyor.yml
@@ -1,4 +1,4 @@
|
||||
# Copyright 2016-2018 Peter Dimov
|
||||
# Copyright 2016-2020 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -21,6 +21,14 @@ environment:
|
||||
TOOLSET: msvc-14.1
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
TOOLSET: clang-win
|
||||
ADDRMD: 64
|
||||
CXXSTD: 14,17
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
TOOLSET: msvc-14.2
|
||||
ADDRMD: 32,64
|
||||
CXXSTD: 14,17
|
||||
|
||||
install:
|
||||
- set BOOST_BRANCH=develop
|
||||
@@ -28,8 +36,6 @@ install:
|
||||
- cd ..
|
||||
- git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
|
||||
- cd boost-root
|
||||
- git submodule update --init tools/build
|
||||
- git submodule update --init libs/config
|
||||
- git submodule update --init tools/boostdep
|
||||
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\variant2\
|
||||
- python tools/boostdep/depinst/depinst.py variant2
|
||||
@@ -41,4 +47,4 @@ build: off
|
||||
test_script:
|
||||
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
|
||||
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
|
||||
- b2 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
|
||||
- b2 -j3 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
////
|
||||
Copyright 2019 Peter Dimov
|
||||
Copyright 2019, 2020 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
@@ -11,6 +11,19 @@ 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`.
|
||||
* `variant<T...>` is now trivial when all types in `T...` are trivial.
|
||||
This improves performance by enabling it to be passed to, and returned
|
||||
from, functions in registers.
|
||||
|
||||
## Changes in 1.71.0
|
||||
|
||||
After the Boost formal review, the implementation has been
|
||||
|
||||
@@ -169,8 +169,6 @@ The main differences between this implementation and `std::variant` are:
|
||||
`variant<int, float>` is provided as the member function `subset<U...>`.
|
||||
(This operation can throw if the current state of the variant cannot be
|
||||
represented.)
|
||||
* `variant<T...>` is not (yet) trivial when all contained types are trivial,
|
||||
as mandated by {cpp}17.
|
||||
* The {cpp}20 additions and changes to `std::variant` have not yet been
|
||||
implemented.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -18,12 +18,14 @@
|
||||
#endif
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
#include <initializer_list>
|
||||
#include <utility>
|
||||
#include <functional> // std::hash
|
||||
|
||||
//
|
||||
|
||||
@@ -502,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>
|
||||
{
|
||||
@@ -547,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...>
|
||||
{
|
||||
@@ -588,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;
|
||||
@@ -624,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 {};
|
||||
|
||||
@@ -1050,20 +1245,317 @@ template<class T> struct is_nothrow_swappable: mp11::mp_valid<det2::is_nothrow_s
|
||||
|
||||
#endif
|
||||
|
||||
// variant_cc_base
|
||||
|
||||
template<bool CopyConstructible, bool TriviallyCopyConstructible, class... T> struct variant_cc_base_impl;
|
||||
|
||||
template<class... T> using variant_cc_base = variant_cc_base_impl<
|
||||
mp11::mp_all<std::is_copy_constructible<T>...>::value,
|
||||
mp11::mp_all<detail::is_trivially_copy_constructible<T>...>::value,
|
||||
T...>;
|
||||
|
||||
template<class... T> struct variant_cc_base_impl<true, true, T...>: public variant_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_cc_base_impl() = default;
|
||||
variant_cc_base_impl( variant_cc_base_impl const& ) = default;
|
||||
variant_cc_base_impl( variant_cc_base_impl && ) = default;
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<bool B, class... T> struct variant_cc_base_impl<false, B, T...>: public variant_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_cc_base_impl() = default;
|
||||
variant_cc_base_impl( variant_cc_base_impl const& ) = delete;
|
||||
variant_cc_base_impl( variant_cc_base_impl && ) = default;
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl const& ) = default;
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<class... T> struct variant_cc_base_impl<true, false, T...>: public variant_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
variant_cc_base_impl() = default;
|
||||
|
||||
// copy constructor
|
||||
|
||||
private:
|
||||
|
||||
struct L1
|
||||
{
|
||||
variant_base * this_;
|
||||
variant_base const & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->_replace( i, r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
variant_cc_base_impl( variant_cc_base_impl const& r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
|
||||
: variant_base()
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
|
||||
}
|
||||
|
||||
// move constructor
|
||||
|
||||
variant_cc_base_impl( variant_cc_base_impl && ) = default;
|
||||
|
||||
// assignment
|
||||
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl const & ) = default;
|
||||
variant_cc_base_impl& operator=( variant_cc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
// variant_ca_base
|
||||
|
||||
template<bool CopyAssignable, bool TriviallyCopyAssignable, class... T> struct variant_ca_base_impl;
|
||||
|
||||
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,
|
||||
T...>;
|
||||
|
||||
template<class... T> struct variant_ca_base_impl<true, true, T...>: public variant_cc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_cc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_ca_base_impl() = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl const& ) = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl && ) = default;
|
||||
variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = default;
|
||||
variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<bool B, class... T> struct variant_ca_base_impl<false, B, T...>: public variant_cc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_cc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_ca_base_impl() = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl const& ) = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl && ) = default;
|
||||
variant_ca_base_impl& operator=( variant_ca_base_impl const& ) = delete;
|
||||
variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<class... T> struct variant_ca_base_impl<true, false, T...>: public variant_cc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_cc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
variant_ca_base_impl() = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl const& ) = default;
|
||||
variant_ca_base_impl( variant_ca_base_impl && ) = default;
|
||||
|
||||
// copy assignment
|
||||
|
||||
private:
|
||||
|
||||
struct L3
|
||||
{
|
||||
variant_base * this_;
|
||||
variant_base const & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->template emplace<I::value>( r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
BOOST_CXX14_CONSTEXPR variant_ca_base_impl& operator=( variant_ca_base_impl const & r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
|
||||
return *this;
|
||||
}
|
||||
|
||||
// move assignment
|
||||
|
||||
variant_ca_base_impl& operator=( variant_ca_base_impl && ) = default;
|
||||
};
|
||||
|
||||
// variant_mc_base
|
||||
|
||||
template<bool MoveConstructible, bool TriviallyMoveConstructible, class... T> struct variant_mc_base_impl;
|
||||
|
||||
template<class... T> using variant_mc_base = variant_mc_base_impl<
|
||||
mp11::mp_all<std::is_move_constructible<T>...>::value,
|
||||
mp11::mp_all<detail::is_trivially_move_constructible<T>...>::value,
|
||||
T...>;
|
||||
|
||||
template<class... T> struct variant_mc_base_impl<true, true, T...>: public variant_ca_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_ca_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_mc_base_impl() = default;
|
||||
variant_mc_base_impl( variant_mc_base_impl const& ) = default;
|
||||
variant_mc_base_impl( variant_mc_base_impl && ) = default;
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<bool B, class... T> struct variant_mc_base_impl<false, B, T...>: public variant_ca_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_ca_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_mc_base_impl() = default;
|
||||
variant_mc_base_impl( variant_mc_base_impl const& ) = default;
|
||||
variant_mc_base_impl( variant_mc_base_impl && ) = delete;
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl const& ) = default;
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<class... T> struct variant_mc_base_impl<true, false, T...>: public variant_ca_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_ca_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
variant_mc_base_impl() = default;
|
||||
variant_mc_base_impl( variant_mc_base_impl const& ) = default;
|
||||
|
||||
// move constructor
|
||||
|
||||
private:
|
||||
|
||||
struct L2
|
||||
{
|
||||
variant_base * this_;
|
||||
variant_base & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->_replace( i, std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
variant_mc_base_impl( variant_mc_base_impl && r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
|
||||
}
|
||||
|
||||
// assignment
|
||||
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl const & ) = default;
|
||||
variant_mc_base_impl& operator=( variant_mc_base_impl && ) = default;
|
||||
};
|
||||
|
||||
// variant_ma_base
|
||||
|
||||
template<bool MoveAssignable, bool TriviallyMoveAssignable, class... T> struct variant_ma_base_impl;
|
||||
|
||||
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,
|
||||
T...>;
|
||||
|
||||
template<class... T> struct variant_ma_base_impl<true, true, T...>: public variant_mc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_mc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_ma_base_impl() = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl const& ) = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl && ) = default;
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl && ) = default;
|
||||
};
|
||||
|
||||
template<bool B, class... T> struct variant_ma_base_impl<false, B, T...>: public variant_mc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_mc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
variant_ma_base_impl() = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl const& ) = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl && ) = default;
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl const& ) = default;
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl && ) = delete;
|
||||
};
|
||||
|
||||
template<class... T> struct variant_ma_base_impl<true, false, T...>: public variant_mc_base<T...>
|
||||
{
|
||||
using variant_base = detail::variant_mc_base<T...>;
|
||||
using variant_base::variant_base;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
variant_ma_base_impl() = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl const& ) = default;
|
||||
variant_ma_base_impl( variant_ma_base_impl && ) = default;
|
||||
|
||||
// copy assignment
|
||||
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl const & ) = default;
|
||||
|
||||
// move assignment
|
||||
|
||||
private:
|
||||
|
||||
struct L4
|
||||
{
|
||||
variant_base * this_;
|
||||
variant_base & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->template emplace<I::value>( std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
variant_ma_base_impl& operator=( variant_ma_base_impl && r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// variant
|
||||
|
||||
template<class... T> class variant: private detail::variant_base<T...>
|
||||
template<class... T> class variant: private detail::variant_ma_base<T...>
|
||||
{
|
||||
private:
|
||||
|
||||
using variant_base = detail::variant_base<T...>;
|
||||
|
||||
private:
|
||||
|
||||
variant( variant const volatile& r ) = delete;
|
||||
variant& operator=( variant const volatile& r ) = delete;
|
||||
using variant_base = detail::variant_ma_base<T...>;
|
||||
|
||||
public:
|
||||
|
||||
@@ -1076,71 +1568,8 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>, E1>
|
||||
>
|
||||
constexpr variant( variant const& r ) noexcept
|
||||
: variant_base( static_cast<variant_base const&>(r) )
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct L1
|
||||
{
|
||||
variant_base * this_;
|
||||
variant const & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->_replace( i, r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_copy_constructible<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>...>, E1>
|
||||
>
|
||||
variant( variant const& r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L1{ this, r } );
|
||||
}
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<detail::is_trivially_move_constructible<T>...>, E1>
|
||||
>
|
||||
constexpr variant( variant && r ) noexcept
|
||||
: variant_base( static_cast<variant_base&&>(r) )
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct L2
|
||||
{
|
||||
variant_base * this_;
|
||||
variant & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->_replace( i, std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<detail::is_trivially_move_constructible<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>...>, E1>
|
||||
>
|
||||
variant( variant && r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L2{ this, r } );
|
||||
}
|
||||
// variant( variant const& ) = default;
|
||||
// variant( variant && ) = default;
|
||||
|
||||
template<class U,
|
||||
class Ud = typename std::decay<U>::type,
|
||||
@@ -1175,75 +1604,9 @@ public:
|
||||
}
|
||||
|
||||
// assignment
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) noexcept
|
||||
{
|
||||
static_cast<variant_base&>( *this ) = static_cast<variant_base const&>( r );
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct L3
|
||||
{
|
||||
variant * this_;
|
||||
variant const & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->variant_base::template emplace<I::value>( r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_copy_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L3{ this, r } );
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant && r ) noexcept
|
||||
{
|
||||
static_cast<variant_base&>( *this ) = static_cast<variant_base&&>( r );
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
struct L4
|
||||
{
|
||||
variant * this_;
|
||||
variant & r;
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
this_->variant_base::template emplace<I::value>( std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>, E1>
|
||||
>
|
||||
variant& operator=( variant && r )
|
||||
noexcept( mp11::mp_all<std::is_nothrow_move_constructible<T>...>::value )
|
||||
{
|
||||
mp11::mp_with_index<sizeof...(T)>( r.index(), L4{ this, r } );
|
||||
return *this;
|
||||
}
|
||||
// variant& operator=( variant const& ) = default;
|
||||
// variant& operator=( variant && ) = default;
|
||||
|
||||
template<class U,
|
||||
class E1 = typename std::enable_if<!std::is_same<typename std::decay<U>::type, variant>::value>::type,
|
||||
@@ -1598,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;
|
||||
@@ -1637,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)();
|
||||
}
|
||||
@@ -1651,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) ) );
|
||||
}
|
||||
@@ -1664,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 )
|
||||
@@ -1690,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;
|
||||
|
||||
@@ -1722,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;
|
||||
|
||||
@@ -1748,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)... );
|
||||
|
||||
});
|
||||
}
|
||||
@@ -1785,9 +2182,92 @@ void swap( variant<T...> & v, variant<T...> & w )
|
||||
v.swap( w );
|
||||
}
|
||||
|
||||
// hashing support
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class V> struct hash_value_L
|
||||
{
|
||||
V const & v;
|
||||
|
||||
template<class I> std::size_t operator()( I ) const
|
||||
{
|
||||
boost::ulong_long_type hv = ( boost::ulong_long_type( 0xCBF29CE4 ) << 32 ) + 0x84222325;
|
||||
boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3;
|
||||
|
||||
// index
|
||||
|
||||
hv ^= I::value;
|
||||
hv *= prime;
|
||||
|
||||
// value
|
||||
|
||||
auto const & t = unsafe_get<I::value>( v );
|
||||
|
||||
hv ^= std::hash<remove_cv_ref_t<decltype(t)>>()( t );
|
||||
hv *= prime;
|
||||
|
||||
return static_cast<std::size_t>( hv );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
inline std::size_t hash_value( monostate const & )
|
||||
{
|
||||
return 0xA7EE4757u;
|
||||
}
|
||||
|
||||
template<class... T> std::size_t hash_value( variant<T...> const & v )
|
||||
{
|
||||
return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< variant<T...> >{ v } );
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<class T> using is_hash_enabled = std::is_default_constructible< std::hash<typename std::remove_const<T>::type> >;
|
||||
|
||||
template<class V, bool E = mp11::mp_all_of<V, is_hash_enabled>::value> struct std_hash_impl;
|
||||
|
||||
template<class V> struct std_hash_impl<V, false>
|
||||
{
|
||||
std_hash_impl() = delete;
|
||||
std_hash_impl( std_hash_impl const& ) = delete;
|
||||
std_hash_impl& operator=( std_hash_impl const& ) = delete;
|
||||
};
|
||||
|
||||
template<class V> struct std_hash_impl<V, true>
|
||||
{
|
||||
std::size_t operator()( V const & v ) const
|
||||
{
|
||||
return hash_value( v );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
} // namespace variant2
|
||||
} // namespace boost
|
||||
|
||||
namespace std
|
||||
{
|
||||
|
||||
template<class... T> struct hash< ::boost::variant2::variant<T...> >: public ::boost::variant2::detail::std_hash_impl< ::boost::variant2::variant<T...> >
|
||||
{
|
||||
};
|
||||
|
||||
template<> struct hash< ::boost::variant2::monostate >
|
||||
{
|
||||
std::size_t operator()( ::boost::variant2::monostate const & v ) const
|
||||
{
|
||||
return hash_value( v );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1910
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ include(BoostTestJamfile OPTIONAL RESULT_VARIABLE HAVE_BOOST_TEST)
|
||||
|
||||
if(HAVE_BOOST_TEST)
|
||||
|
||||
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::variant2 Boost::core)
|
||||
boost_test_jamfile(FILE Jamfile LINK_LIBRARIES Boost::variant2 Boost::core Boost::container_hash)
|
||||
|
||||
endif()
|
||||
|
||||
34
test/Jamfile
34
test/Jamfile
@@ -12,7 +12,7 @@ import ../../config/checks/config : requires ;
|
||||
project
|
||||
: default-build
|
||||
|
||||
<warnings>all
|
||||
<warnings>extra
|
||||
|
||||
: requirements
|
||||
|
||||
@@ -29,16 +29,16 @@ run variant_size.cpp ;
|
||||
run variant_alternative.cpp ;
|
||||
|
||||
run variant_holds_alternative.cpp ;
|
||||
compile variant_holds_alternative_cx.cpp ;
|
||||
compile variant_holds_alternative_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_get_by_index.cpp ;
|
||||
compile variant_get_by_index_cx.cpp ;
|
||||
compile variant_get_by_index_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_get_by_type.cpp ;
|
||||
compile variant_get_by_type_cx.cpp ;
|
||||
compile variant_get_by_type_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_default_construct.cpp ;
|
||||
compile variant_default_construct_cx.cpp ;
|
||||
compile variant_default_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_copy_construct.cpp ;
|
||||
compile variant_copy_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
@@ -47,13 +47,13 @@ run variant_move_construct.cpp ;
|
||||
compile variant_move_construct_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
|
||||
run variant_value_construct.cpp ;
|
||||
compile variant_value_construct_cx.cpp ;
|
||||
compile variant_value_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_in_place_index_construct.cpp ;
|
||||
compile variant_in_place_index_construct_cx.cpp ;
|
||||
compile variant_in_place_index_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_in_place_type_construct.cpp ;
|
||||
compile variant_in_place_type_construct_cx.cpp ;
|
||||
compile variant_in_place_type_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_copy_assign.cpp ;
|
||||
compile variant_copy_assign_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
@@ -99,9 +99,23 @@ local NX =
|
||||
;
|
||||
|
||||
run variant_get_by_index.cpp throw_exception.cpp : : : $(NX) : variant_get_by_index_nx ;
|
||||
compile variant_get_by_index_cx.cpp : $(NX) : variant_get_by_index_cx_nx ;
|
||||
compile variant_get_by_index_cx.cpp : $(NX) <toolset>msvc-14.0:<build>no : variant_get_by_index_cx_nx ;
|
||||
|
||||
run variant_get_by_type.cpp throw_exception.cpp : : : $(NX) : variant_get_by_type_nx ;
|
||||
compile variant_get_by_type_cx.cpp : $(NX) : variant_get_by_type_cx_nx ;
|
||||
compile variant_get_by_type_cx.cpp : $(NX) <toolset>msvc-14.0:<build>no : variant_get_by_type_cx_nx ;
|
||||
|
||||
run variant_subset.cpp throw_exception.cpp : : : $(NX) : variant_subset_nx ;
|
||||
|
||||
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
|
||||
;
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
@@ -48,12 +50,21 @@ struct Y
|
||||
Y( Y const& ) = delete;
|
||||
};
|
||||
|
||||
struct D
|
||||
{
|
||||
~D() {}
|
||||
};
|
||||
|
||||
inline bool operator==( D, D ) { return true; }
|
||||
|
||||
template<class V> static void test( V const & v )
|
||||
{
|
||||
V v2( v );
|
||||
|
||||
BOOST_TEST_EQ( v.index(), v2.index() );
|
||||
BOOST_TEST( v == v2 );
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_copy_constructible<V>));
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -115,6 +126,12 @@ int main()
|
||||
test( v );
|
||||
}
|
||||
|
||||
#if !BOOST_WORKAROUND( __GNUC__, < 5 )
|
||||
|
||||
test( variant<D>() );
|
||||
|
||||
#endif
|
||||
|
||||
{
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int>>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_nothrow_copy_constructible<variant<int const>>));
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
73
test/variant_hash.cpp
Normal file
73
test/variant_hash.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
|
||||
// Copyright 2020 Peter Dimov.
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( disable: 4244 ) // conversion from int to float, possible loss of data
|
||||
#endif
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/container_hash/hash.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
template<template<class...> class Hash, class T1, class T2, class T3> void test()
|
||||
{
|
||||
variant<T1, T2, T3> v1( in_place_index_t<0>{} );
|
||||
std::size_t h1 = Hash<decltype(v1)>()( v1 );
|
||||
|
||||
variant<T1, T2, T3> v2( in_place_index_t<1>{} );
|
||||
std::size_t h2 = Hash<decltype(v2)>()( v2 );
|
||||
|
||||
variant<T1, T2, T3> v3( in_place_index_t<2>{} );
|
||||
std::size_t h3 = Hash<decltype(v3)>()( v3 );
|
||||
|
||||
BOOST_TEST_NE( h1, h2 );
|
||||
BOOST_TEST_NE( h1, h3 );
|
||||
BOOST_TEST_NE( h2, h3 );
|
||||
}
|
||||
|
||||
template<template<class...> class Hash, class T> void test2()
|
||||
{
|
||||
variant<T> v1( 0 );
|
||||
std::size_t h1 = Hash<decltype(v1)>()( v1 );
|
||||
|
||||
variant<T> v2( 1 );
|
||||
std::size_t h2 = Hash<decltype(v2)>()( v2 );
|
||||
|
||||
variant<T> v3( 2 );
|
||||
std::size_t h3 = Hash<decltype(v3)>()( v3 );
|
||||
|
||||
BOOST_TEST_NE( h1, h2 );
|
||||
BOOST_TEST_NE( h1, h3 );
|
||||
BOOST_TEST_NE( h2, h3 );
|
||||
}
|
||||
|
||||
struct X {};
|
||||
|
||||
int main()
|
||||
{
|
||||
test<std::hash, monostate, monostate, monostate>();
|
||||
test<std::hash, int, int, float>();
|
||||
|
||||
test<boost::hash, monostate, monostate, monostate>();
|
||||
test<boost::hash, int, int, float>();
|
||||
|
||||
test2<std::hash, int>();
|
||||
test2<std::hash, float>();
|
||||
|
||||
test2<boost::hash, int>();
|
||||
test2<boost::hash, float>();
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) && ( !defined(_LIBCPP_STD_VER) || _LIBCPP_STD_VER > 11 )
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled<X> ));
|
||||
|
||||
#endif
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
109
test/variant_many_types.cpp
Normal 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();
|
||||
}
|
||||
103
test/variant_special.cpp
Normal file
103
test/variant_special.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
// 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) && _MSC_VER < 1910
|
||||
# pragma warning(disable: 4503) // decorated name length exceeded
|
||||
#endif
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
using namespace boost::mp11;
|
||||
|
||||
//
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct D
|
||||
{
|
||||
~D() noexcept {}
|
||||
};
|
||||
|
||||
struct CC1
|
||||
{
|
||||
CC1( CC1 const& ) {}
|
||||
};
|
||||
|
||||
struct CC2
|
||||
{
|
||||
CC2( CC2 const& ) = delete;
|
||||
};
|
||||
|
||||
struct MC1
|
||||
{
|
||||
MC1( MC1 && ) {}
|
||||
};
|
||||
|
||||
struct MC2
|
||||
{
|
||||
MC2( MC2 && ) = delete;
|
||||
};
|
||||
|
||||
struct CA1
|
||||
{
|
||||
CA1& operator=( CA1 const& ) { return *this; }
|
||||
};
|
||||
|
||||
struct CA2
|
||||
{
|
||||
CA2& operator=( CA2 const& ) = delete;
|
||||
};
|
||||
|
||||
struct MA1
|
||||
{
|
||||
MA1& operator=( MA1 && ) { return *this; }
|
||||
};
|
||||
|
||||
struct MA2
|
||||
{
|
||||
MA2& operator=( MA2 && ) = delete;
|
||||
};
|
||||
|
||||
struct test
|
||||
{
|
||||
template<class... T> void operator()( mp_list<T...> ) const noexcept
|
||||
{
|
||||
using U = mp_inherit<T...>;
|
||||
|
||||
#if !BOOST_WORKAROUND( __GNUC__, < 5 )
|
||||
|
||||
BOOST_TEST_EQ( std::is_copy_constructible<variant<U>>::value, std::is_copy_constructible<U>::value );
|
||||
BOOST_TEST_EQ( std::is_nothrow_copy_constructible<variant<U>>::value, std::is_nothrow_copy_constructible<U>::value );
|
||||
|
||||
#endif
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910)
|
||||
|
||||
BOOST_TEST_EQ( std::is_move_constructible<variant<U>>::value, std::is_move_constructible<U>::value );
|
||||
|
||||
#else
|
||||
|
||||
BOOST_TEST_GE( std::is_move_constructible<variant<U>>::value, std::is_move_constructible<U>::value );
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_TEST_EQ( std::is_nothrow_move_constructible<variant<U>>::value, std::is_nothrow_move_constructible<U>::value );
|
||||
|
||||
BOOST_TEST_EQ( std::is_copy_assignable<variant<U>>::value, std::is_copy_constructible<U>::value && std::is_copy_assignable<U>::value );
|
||||
BOOST_TEST_EQ( std::is_nothrow_copy_assignable<variant<U>>::value, std::is_nothrow_copy_constructible<U>::value && std::is_copy_assignable<U>::value );
|
||||
|
||||
BOOST_TEST_EQ( std::is_move_assignable<variant<U>>::value, std::is_move_constructible<U>::value && std::is_move_assignable<U>::value );
|
||||
BOOST_TEST_EQ( std::is_nothrow_move_assignable<variant<U>>::value, std::is_nothrow_move_constructible<U>::value && std::is_move_assignable<U>::value );
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
mp_for_each< mp_power_set< mp_list<D, CC1, CC2, MC1, MC2, CA1, CA2, MA1, MA2> > >( test() );
|
||||
return boost::report_errors();
|
||||
}
|
||||
95
test/variant_trivial.cpp
Normal file
95
test/variant_trivial.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
// 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) && _MSC_VER < 1910
|
||||
# pragma warning(disable: 4503) // decorated name length exceeded
|
||||
#endif
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/config/workaround.hpp>
|
||||
|
||||
#include <boost/mp11.hpp>
|
||||
using namespace boost::mp11;
|
||||
|
||||
//
|
||||
|
||||
struct D
|
||||
{
|
||||
~D() noexcept {}
|
||||
};
|
||||
|
||||
struct CC1
|
||||
{
|
||||
CC1( CC1 const& ) noexcept {}
|
||||
};
|
||||
|
||||
struct CC2
|
||||
{
|
||||
CC2( CC2 const& ) = delete;
|
||||
};
|
||||
|
||||
struct MC1
|
||||
{
|
||||
MC1( MC1 && ) noexcept {}
|
||||
};
|
||||
|
||||
struct MC2
|
||||
{
|
||||
MC2( MC2 && ) = delete;
|
||||
};
|
||||
|
||||
struct CA1
|
||||
{
|
||||
CA1& operator=( CA1 const& ) noexcept { return *this; }
|
||||
};
|
||||
|
||||
struct CA2
|
||||
{
|
||||
CA2& operator=( CA2 const& ) = delete;
|
||||
};
|
||||
|
||||
struct MA1
|
||||
{
|
||||
MA1& operator=( MA1 && ) noexcept { return *this; }
|
||||
};
|
||||
|
||||
struct MA2
|
||||
{
|
||||
MA2& operator=( MA2 && ) = delete;
|
||||
};
|
||||
|
||||
using namespace boost::variant2;
|
||||
namespace v2d = boost::variant2::detail;
|
||||
|
||||
struct test
|
||||
{
|
||||
template<class... T> void operator()( mp_list<T...> ) const noexcept
|
||||
{
|
||||
using U = mp_inherit<T...>;
|
||||
|
||||
#if !BOOST_WORKAROUND( __GNUC__, < 5 )
|
||||
|
||||
BOOST_TEST_EQ( v2d::is_trivially_copy_constructible<variant<U>>::value, v2d::is_trivially_copy_constructible<U>::value );
|
||||
BOOST_TEST_EQ( v2d::is_trivially_copy_assignable<variant<U>>::value, std::is_trivially_destructible<U>::value && v2d::is_trivially_copy_constructible<U>::value && v2d::is_trivially_copy_assignable<U>::value );
|
||||
|
||||
#endif
|
||||
|
||||
BOOST_TEST_EQ( std::is_trivially_destructible<variant<U>>::value, std::is_trivially_destructible<U>::value );
|
||||
|
||||
#if !BOOST_WORKAROUND(BOOST_LIBSTDCXX_VERSION, < 50000)
|
||||
|
||||
BOOST_TEST_EQ( v2d::is_trivially_move_constructible<variant<U>>::value, v2d::is_trivially_move_constructible<U>::value );
|
||||
BOOST_TEST_EQ( v2d::is_trivially_move_assignable<variant<U>>::value, std::is_trivially_destructible<U>::value && v2d::is_trivially_move_constructible<U>::value && v2d::is_trivially_move_assignable<U>::value );
|
||||
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
mp_for_each< mp_power_set< mp_list<D, CC1, CC2, MC1, MC2, CA1, CA2, MA1, MA2> > >( test() );
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -37,6 +37,10 @@ struct F
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
BOOST_TEST_EQ( (visit( []{ return 5; } )), 5 );
|
||||
}
|
||||
|
||||
{
|
||||
variant<int> v( 1 );
|
||||
|
||||
|
||||
57
test/variant_visit_derived.cpp
Normal file
57
test/variant_visit_derived.cpp
Normal 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
98
test/variant_visit_r.cpp
Normal 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();
|
||||
}
|
||||
Reference in New Issue
Block a user