Compare commits

...

65 Commits

Author SHA1 Message Date
5c0274a76e glob headers 2022-07-05 10:48:50 +02:00
d34658f4c8 Document operator<< for monostate 2022-01-31 19:19:49 +02:00
5e2bce1baa Add operator<< for monostate 2022-01-31 17:55:26 +02:00
573ef77382 Move unsigned ix_ after the elements to avoid need to adjust rdi (closes #30) 2021-12-09 21:28:35 +02:00
f6cad272d4 Add msvc-14.0 to GHA 2021-12-09 19:59:01 +02:00
3fc7540733 Only define operator<< when all contained types are streamable (refs #31) 2021-12-09 18:39:03 +02:00
e4b4b3f02b Extend msvc-14.2 workaround to 14.3 2021-10-29 02:18:23 +03:00
44d38c4111 Enable syntax highlighting 2021-10-28 23:23:13 +03:00
1ebfb3b689 Add msvc-14.3 to ci.yml 2021-10-28 23:22:20 +03:00
8af1fbde8e Update cmake_subdir_test/CMakeLists.txt 2021-09-21 14:52:38 +03:00
26ce33597d Regenerate CMakeLists.txt 2021-09-21 14:45:20 +03:00
c89713b978 Add CMake tests to ci.yml 2021-09-21 14:31:47 +03:00
10c441c8d7 Update appveyor.yml 2021-09-15 15:11:54 +03:00
09ec260780 Document operator<< 2021-09-15 03:53:13 +03:00
2da13befd7 Work around mysterious errors with gcc, msvc-14.1, and clang-cl 2021-09-15 03:28:29 +03:00
e668c099ce Add operator<< for variant 2021-09-15 02:51:11 +03:00
aebcb9792d Update documentation of visit_by_index 2021-09-15 02:00:33 +03:00
8fd9f830a9 Add proper type deduction to visit_by_index 2021-09-15 01:30:09 +03:00
ed4bebff3d Document visit_by_index 2021-09-14 21:32:57 +03:00
ad06c9b923 Add visit_by_index 2021-09-14 21:06:01 +03:00
de4eb8b6d2 Update README.md 2021-09-11 19:47:34 +03:00
4d69db1441 Extend g++-10 workarounds to 11 2021-09-11 19:23:39 +03:00
095d9770c4 Update ci.yml 2021-09-11 18:36:43 +03:00
cca476fbbc Update documentation 2021-09-11 18:29:17 +03:00
c76af4d3cf Update README.md 2021-09-11 18:26:28 +03:00
1af7b165cf BOOST_VARIANT2_CX14_ASSERT must be empty under C++11 2021-09-11 18:22:46 +03:00
49bff72be0 Define and use a helper macro BOOST_VARIANT2_CX14_ASSERT in constexpr functions 2021-09-11 18:11:17 +03:00
59780ba08e Only assert when C++14 2021-09-11 18:00:29 +03:00
edd70cfd66 Update ci.yml 2021-09-11 17:43:05 +03:00
86c2782dff Update documentation 2021-09-11 17:39:55 +03:00
dce8174550 Make unsafe_get public 2021-09-11 17:29:21 +03:00
9d40bc80f1 Use BOOST_ASSERT instead of assert 2021-09-11 17:23:29 +03:00
be6ddf9fdc Add boost/variant2.hpp 2021-09-11 17:19:09 +03:00
4153a535a0 Update .github/workflows 2021-04-19 20:37:12 +03:00
f374ad68a3 Add -DBUILD_TESTING=ON to .yml files; it's not default anymore 2021-03-19 04:18:08 +02:00
3bc9a57c9b Merge branch 'feature/issue-26' into develop 2021-03-13 18:23:39 +02:00
3ca95a65df Use boost::hash in hash_value, not std::hash (closes #27) 2021-03-13 05:08:03 +02:00
ae1f72671e Add test for types supported by boost::hash, but not by std::hash 2021-03-13 04:50:01 +02:00
a2dab8c7d3 Refactor detail::hash_value_L 2021-03-13 04:10:41 +02:00
f39a71ed2f Merge branch 'feature/issue-26-nofix' into feature/issue-26 2021-03-13 01:09:46 +02:00
06dde96400 Merge branch 'develop' into feature/issue-26-nofix 2021-03-13 01:09:17 +02:00
8be0a4a5fe Update copyright 2021-03-12 23:42:32 +02:00
90cda5339f Disable U&& constructor for derived types 2021-03-12 23:40:14 +02:00
afb0aafd64 Change clangs to bionic 2021-03-12 20:18:24 +02:00
f586dc8848 Add test for inherited constructors (refs #26) 2021-03-12 20:15:09 +02:00
20b9175932 Add cxxstd=latest to Appveyor 2021-03-08 04:04:35 +02:00
fb3ce863ff Add MSVC workaround for monospace constexpr (refs #25) 2021-03-08 03:26:40 +02:00
8ec0bf448a Add monospace relational tests (refs #25) 2021-03-08 03:01:21 +02:00
6d19e6be68 Update revision history 2021-03-07 00:51:28 +02:00
d8552b23ae UBSan on clang 7 is broken on Ubuntu 2021-03-01 06:35:38 +02:00
f44aba09a2 Update .travis.yml 2021-03-01 00:26:43 +02:00
99cc1db385 Fix documentation for emplace effects 2021-01-25 03:49:42 +02:00
6d848c5af6 Update GCC workarounds in constexpr in-place construct tests 2021-01-25 03:44:24 +02:00
3c9f4e56bf Fix visit codegen regression when NDEBUG is not defined 2021-01-24 17:27:24 +02:00
3015e56bcb GCC bug 63707 has been fixed for GCC 11 2021-01-23 20:36:12 +02:00
7c37053950 Merge branch 'develop' into feature/double-opt 2021-01-13 05:06:00 +02:00
60995edb41 Remove g++ 4.7 from GHA 2021-01-13 05:01:44 +02:00
84a2c175d0 Use variant=release for variant_visit_r under g++/windows 2021-01-13 04:44:56 +02:00
ea3268feb4 Add .github/workflows 2021-01-13 04:19:15 +02:00
6de876954a Merge branch 'develop' into feature/double-opt 2021-01-13 02:32:32 +02:00
efc1d5acca Add more tests to variant_emplace_index.cpp 2021-01-13 02:32:05 +02:00
453b00dec8 Use (i+1)*2+j for the internal index in the double-buffered case, to avoid branches 2021-01-13 02:10:12 +02:00
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
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
93b8618e94 Update maintainer e-mail 2020-12-12 01:08:09 +02:00
29 changed files with 1297 additions and 237 deletions

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

@ -0,0 +1,358 @@
name: CI
on:
pull_request:
push:
branches:
- master
- develop
- feature/**
env:
UBSAN_OPTIONS: print_stacktrace=1
jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-4.8
cxxstd: "03,11"
os: ubuntu-18.04
install: g++-4.8
- toolset: gcc-5
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: g++-5
- toolset: gcc-6
cxxstd: "03,11,14,1z"
os: ubuntu-18.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
install: g++-8
- toolset: gcc-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
- toolset: gcc-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-10
- toolset: gcc-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: g++-11
- toolset: clang
compiler: clang++-3.9
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-3.9
- toolset: clang
compiler: clang++-4.0
cxxstd: "03,11,14"
os: ubuntu-18.04
install: clang-4.0
- toolset: clang
compiler: clang++-5.0
cxxstd: "03,11,14,1z"
os: ubuntu-18.04
install: clang-5.0
- toolset: clang
compiler: clang++-6.0
cxxstd: "03,11,14,17"
os: ubuntu-18.04
install: clang-6.0
- 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"
os: ubuntu-20.04
install: clang-8
- toolset: clang
compiler: clang++-9
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-9
- toolset: clang
compiler: clang++-10
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-10
- toolset: clang
compiler: clang++-11
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-11
- toolset: clang
compiler: clang++-12
cxxstd: "03,11,14,17,2a"
os: ubuntu-20.04
install: clang-12
- 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.0
cxxstd: "14"
addrmd: 32,64
os: windows-2019
- 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: msvc-14.3
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- 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
posix-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- 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
- name: Use library with add_subdirectory
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- 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
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DCMAKE_INSTALL_PREFIX=~/.local ..
- name: Install
run: |
cd ../boost-root/__build__
cmake --build . --target install
- name: Use the installed library
run: |
cd ../boost-root/libs/$LIBRARY/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=~/.local ..
cmake --build .
ctest --output-on-failure --no-tests=error
posix-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-18.04
- os: ubuntu-20.04
- 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
- name: Configure
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=$LIBRARY -DBUILD_TESTING=ON ..
- name: Build tests
run: |
cd ../boost-root/__build__
cmake --build . --target tests
- name: Run tests
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error

View File

@ -1,4 +1,4 @@
# Copyright 2016-2019 Peter Dimov
# Copyright 2016-2021 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)
@ -95,7 +95,7 @@ matrix:
- os: linux
dist: bionic
compiler: g++-10
env: TOOLSET=gcc COMPILER=g++-10 CXXSTD=11,14,17,2a
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-10 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
addons:
apt:
packages:
@ -103,21 +103,6 @@ matrix:
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
addons:
apt:
packages:
- g++-8
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
@ -180,6 +165,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-5.0
env: TOOLSET=clang COMPILER=clang++-5.0 CXXSTD=11,14,1z
addons:
@ -190,6 +176,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-6.0
env: TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=11,14,17
addons:
@ -200,6 +187,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-7
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=11,14,17,2a
addons:
@ -208,9 +196,10 @@ matrix:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-7
- llvm-toolchain-bionic-7
- os: linux
dist: bionic
compiler: clang++-8
env: TOOLSET=clang COMPILER=clang++-8 CXXSTD=11,14,17,2a
addons:
@ -219,10 +208,10 @@ matrix:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- llvm-toolchain-bionic-8
- os: linux
dist: xenial
dist: bionic
compiler: clang++-9
env: TOOLSET=clang COMPILER=clang++-9 CXXSTD=11,14,17,2a
addons:
@ -231,11 +220,11 @@ matrix:
- clang-9
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: xenial
dist: bionic
compiler: clang++-10
env: TOOLSET=clang COMPILER=clang++-10 CXXSTD=11,14,17,2a
addons:
@ -244,19 +233,34 @@ matrix:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main'
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-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
dist: bionic
compiler: clang++-11
env: TOOLSET=clang COMPILER=clang++-11 CXXSTD=11,14,17,2a
addons:
apt:
packages:
- clang-8
- clang-11
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: bionic
compiler: clang++-12
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-12 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-12
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: trusty
@ -268,18 +272,14 @@ matrix:
- libc++-dev
- os: linux
dist: trusty
dist: bionic
compiler: clang++-libc++
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1
env: TOOLSET=clang COMPILER=clang++-libc++ CXXSTD=11,14,17,2a
addons:
apt:
packages:
- libc++-dev
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z
- os: osx
compiler: clang++
env: UBSAN=1 TOOLSET=clang COMPILER=clang++ CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1
@ -288,7 +288,7 @@ matrix:
env: CMAKE_TEST=1
script:
- mkdir __build__ && cd __build__
- cmake -DBOOST_ENABLE_CMAKE=1 -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=variant2 ..
- cmake -DBOOST_ENABLE_CMAKE=1 -DBUILD_TESTING=ON -DBoost_VERBOSE=1 -DBOOST_INCLUDE_LIBRARIES=variant2 ..
- ctest --output-on-failure -R boost_variant2
- os: linux

View File

@ -1,8 +1,11 @@
# Copyright 2018, 2019 Peter Dimov
# Generated by `boostdep --cmake variant2`
# Copyright 2020, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# http://www.boost.org/LICENSE_1_0.txt
# https://www.boost.org/LICENSE_1_0.txt
cmake_minimum_required(VERSION 3.5...3.16)
if(NOT DEFINED IDF_TARGET)
cmake_minimum_required(VERSION 3.8...3.20)
project(boost_variant2 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
@ -13,12 +16,34 @@ target_include_directories(boost_variant2 INTERFACE include)
target_link_libraries(boost_variant2
INTERFACE
Boost::assert
Boost::config
Boost::mp11
)
if(BUILD_TESTING)
target_compile_features(boost_variant2 INTERFACE cxx_std_11)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test)
endif()
else()
FILE(GLOB_RECURSE headers include/*.h include/*.hpp)
idf_component_register(
SRCS
${headers}
INCLUDE_DIRS
include
REQUIRES
boost_assert
boost_config
boost_mp11
)
endif()

View File

@ -1,21 +1,18 @@
# variant2
# Boost.Variant2
This repository contains a never-valueless, strong guarantee, C++11/14/17
implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant).
See [the documentation](https://www.boost.org/libs/variant2)
for more information.
The code requires [Boost.Mp11](https://github.com/boostorg/mp11) and
Boost.Config.
The library is part of Boost, starting from release 1.71, but the header
`variant.hpp` will also work [standalone](https://godbolt.org/z/nVUNKX).
The library is part of Boost, starting from release 1.71. It depends on
Boost.Mp11, Boost.Config, and Boost.Assert.
Supported compilers:
* g++ 4.8 or later with `-std=c++11` or above
* clang++ 3.5 or later with `-std=c++11` or above
* clang++ 3.9 or later with `-std=c++11` or above
* Visual Studio 2015, 2017, 2019
Tested on [Travis](https://travis-ci.org/boostorg/variant2/) and
Tested on [Github Actions](https://github.com/boostorg/variant2/actions) and
[Appveyor](https://ci.appveyor.com/project/pdimov/variant2-fkab9).

View File

@ -1,4 +1,4 @@
# Copyright 2016-2020 Peter Dimov
# Copyright 2016-2021 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)
@ -20,15 +20,19 @@ environment:
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
ADDRMD: 32,64
CXXSTD: 14,17
CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: clang-win
ADDRMD: 64
CXXSTD: 14,17
CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2
ADDRMD: 32,64
CXXSTD: 14,17
CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: clang-win
ADDRMD: 64
CXXSTD: 14,17,latest
install:
- set BOOST_BRANCH=develop
@ -47,4 +51,4 @@ build: off
test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release
- b2 -j3 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release embed-manifest-via=linker

View File

@ -13,6 +13,8 @@ Peter Dimov
:toclevels: 4
:idprefix:
:docinfo: private-footer
:source-highlighter: rouge
:source-language: c++
:leveloffset: +1

View File

@ -1,16 +1,28 @@
////
Copyright 2019, 2020 Peter Dimov
Copyright 2019-2021 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
https://www.boost.org/LICENSE_1_0.txt
////
[#changelog]
# Revision History
:idprefix: changelog_
## Changes in 1.79.0
* Added `operator<<` for `monostate`.
## Changes in 1.78.0
* Added `<boost/variant2.hpp>`.
* Added `unsafe_get<I>`.
* Added `visit_by_index`.
* Added `operator<<`.
## Changes in 1.76.0
* Improved generated code for the double buffered case.
## Changes in 1.74.0
* Added support for derived types in `visit`

View File

@ -169,6 +169,10 @@ 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.)
* `unsafe_get`, an unchecked alternative to `get` and `get_if`, is provided
as an extension.
* `visit_by_index`, a visitation function that takes a single variant and a
number of function objects, one per alternative, is provided as an extension.
* The {cpp}20 additions and changes to `std::variant` have not yet been
implemented.

View File

@ -1,10 +1,7 @@
////
Copyright 2019 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
https://www.boost.org/LICENSE_1_0.txt
////
[#implementation]
@ -13,13 +10,13 @@ http://www.boost.org/LICENSE_1_0.txt
## Dependencies
This implementation only depends on Boost.Config and Boost.Mp11.
This implementation only depends on Boost.Config, Boost.Assert, and Boost.Mp11.
## Supported Compilers
* GCC 4.8 or later with `-std=c++11` or above
* Clang 3.5 or later with `-std=c++11` or above
* Clang 3.9 or later with `-std=c++11` or above
* Visual Studio 2015, 2017, 2019
Tested on https://travis-ci.org/boostorg/variant2/[Travis] and
Tested on https://github.com/boostorg/variant2/actions[Github Actions] and
https://ci.appveyor.com/project/pdimov/variant2-fkab9[Appveyor].

View File

@ -1,10 +1,7 @@
////
Copyright 2018, 2019 Peter Dimov
Copyright 2018-2021 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
https://www.boost.org/LICENSE_1_0.txt
////
[#reference]
@ -117,6 +114,21 @@ template<class U, class... T>
constexpr add_pointer_t<const U>
get_if(const variant<T...>* v) noexcept;
// unsafe_get (extension)
template<size_t I, class... T>
constexpr variant_alternative_t<I, variant<T...>>&
unsafe_get(variant<T...>& v);
template<size_t I, class... T>
constexpr variant_alternative_t<I, variant<T...>>&&
unsafe_get(variant<T...>&& v);
template<size_t I, class... T>
constexpr const variant_alternative_t<I, variant<T...>>&
unsafe_get(const variant<T...>& v);
template<size_t I, class... T>
constexpr const variant_alternative_t<I, variant<T...>>&&
unsafe_get(const variant<T...>&& v);
// relational operators
template<class... T>
@ -132,11 +144,21 @@ template<class... T>
template<class... T>
constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w);
// swap
template<class... T>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
// visit
template<class R = /*unspecified*/, class F, class... V>
constexpr /*see below*/ visit(F&& f, V&&... v);
// visit_by_index (extension)
template<class R = /*unspecified*/, class V, class... F>
constexpr /*see below*/ visit_by_index(V&& v, F&&.. f);
// monostate
struct monostate {};
@ -148,10 +170,15 @@ constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
// swap
// stream insertion (extension)
template<class... T>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
template<class Ch, class Tr, class... T>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, variant<T...> const& v );
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, monostate const& v );
// bad_variant_access
@ -490,8 +517,8 @@ template<size_t I, class... A>
+
Requires: :: `I < sizeof...(T)`.
Effects: ::
Destroys the currently contained value, then initializes a new contained
value as if using the expression `Ti(std::forward<A>(a)...)`.
Initializes a new contained value as if using the expression
`Ti(std::forward<A>(a)...)`, then destroys the currently contained value.
Ensures: :: `index() == I`.
Returns: :: A reference to the new contained value.
Throws: ::
@ -511,8 +538,8 @@ template<size_t I, class V, class... A>
+
Requires: :: `I < sizeof...(T)`.
Effects: ::
Destroys the currently contained value, then initializes a new contained
value as if using the expression `Ti(il, std::forward<A>(a)...)`.
Initializes a new contained value as if using the expression
`Ti(il, std::forward<A>(a)...)`, then destroys the currently contained value.
Ensures: :: `index() == I`.
Returns: :: A reference to the new contained value.
Throws: ::
@ -775,6 +802,34 @@ Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the
Effects: :: Equivalent to: `return get_if<I>(v);` with `I` being
the zero-based index of `U` in `T...`.
### unsafe_get (extension)
```
template<size_t I, class... T>
constexpr variant_alternative_t<I, variant<T...>>&
unsafe_get(variant<T...>& v);
```
```
template<size_t I, class... T>
constexpr variant_alternative_t<I, variant<T...>>&&
unsafe_get(variant<T...>&& v);
```
```
template<size_t I, class... T>
constexpr const variant_alternative_t<I, variant<T...>>&
unsafe_get(const variant<T...>& v);
```
```
template<size_t I, class... T>
constexpr const variant_alternative_t<I, variant<T...>>&&
unsafe_get(const variant<T...>&& v);
```
[none]
* {blank}
+
Requires: :: `v.index() == I`.
Returns: :: a reference to the object stored in the variant.
### Relational Operators
```
@ -835,6 +890,18 @@ template<class... T>
Returns: ::
`w \<= v`.
### swap
```
template<class... T>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
```
[none]
* {blank}
+
Effects: ::
Equivalent to `v.swap(w)`.
### visit
```
@ -851,17 +918,50 @@ Remarks: :: If `R` is given explicitly, as in `visit<int>`, the return
of `F` to the variant alternatives must have the same return type for
this deduction to succeed.
### swap
### visit_by_index (extension)
```
template<class... T>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
template<class R = /*unspecified*/, class V, class... F>
constexpr /*see below*/ visit_by_index(V&& v, F&&.. f);
```
[none]
* {blank}
+
Requires: :: `variant_size<V>::value == sizeof...(F)`, or the program is ill-formed.
Returns: :: `std::forward<Fi>(fi)(get<i>(std::forward<V>(v)))`, where
`i` is `v.index()` and `Fi` and `fi` are the `i`-th element of `F...` and `f...`
accordingly.
Remarks: :: If `R` is given explicitly, as in `visit_by_index<int>`, the return
type is `R`. Otherwise, it's deduced from `F...` and `V`. All the applications
of `Fi` to the corresponding variant alternatives must have the same return type
for this deduction to succeed.
### Stream Insertion (extension)
```
template<class Ch, class Tr, class... T>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, variant<T...> const& v );
```
[none]
* {blank}
+
Requires: ::
`sizeof...(T) != 0`.
Returns: ::
`os << get<I>(v)`, where `I` is `v.index()`.
```
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>&
operator<<( std::basic_ostream<Ch, Tr>& os, monostate const& v );
```
[none]
* {blank}
+
Effects: ::
Equivalent to `v.swap(w)`.
`os << "monostate"`.
Returns: ::
`os`.
### bad_variant_access
@ -878,3 +978,7 @@ public:
}
};
```
## <boost/variant2.hpp>
This convenience header includes `<boost/variant2/variant.hpp>`.

View File

@ -0,0 +1,10 @@
#ifndef BOOST_VARIANT2_HPP_INCLUDED
#define BOOST_VARIANT2_HPP_INCLUDED
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#endif // #ifndef BOOST_VARIANT2_HPP_INCLUDED

View File

@ -13,19 +13,19 @@
# pragma warning( disable: 4521 4522 ) // multiple copy operators
#endif
#ifndef BOOST_MP11_HPP_INCLUDED
#include <boost/mp11.hpp>
#endif
#include <boost/assert.hpp>
#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
#include <cstdint>
#include <iosfwd>
//
@ -38,6 +38,8 @@ BOOST_NORETURN void throw_exception( std::exception const & e ); // user defined
#endif
template<class T> struct hash;
namespace variant2
{
@ -81,6 +83,8 @@ struct monostate
{
};
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1940)
constexpr bool operator<(monostate, monostate) noexcept { return false; }
constexpr bool operator>(monostate, monostate) noexcept { return false; }
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
@ -88,6 +92,17 @@ constexpr bool operator>=(monostate, monostate) noexcept { return true; }
constexpr bool operator==(monostate, monostate) noexcept { return true; }
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
#else
constexpr bool operator<(monostate const&, monostate const&) noexcept { return false; }
constexpr bool operator>(monostate const&, monostate const&) noexcept { return false; }
constexpr bool operator<=(monostate const&, monostate const&) noexcept { return true; }
constexpr bool operator>=(monostate const&, monostate const&) noexcept { return true; }
constexpr bool operator==(monostate const&, monostate const&) noexcept { return true; }
constexpr bool operator!=(monostate const&, monostate const&) noexcept { return false; }
#endif
// variant forward declaration
template<class... T> class variant;
@ -351,37 +366,50 @@ template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T
#endif
}
// detail::unsafe_get (for visit)
// unsafe_get
namespace detail
{
#if !defined(BOOST_NO_CXX14_CONSTEXPR)
# define BOOST_VARIANT2_CX14_ASSERT(expr) BOOST_ASSERT(expr);
#else
# define BOOST_VARIANT2_CX14_ASSERT(expr)
#endif
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
{
static_assert( I < sizeof...(T), "Index out of bounds" );
BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
return v._get_impl( mp11::mp_size_t<I>() );
}
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
{
static_assert( I < sizeof...(T), "Index out of bounds" );
BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
}
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
{
static_assert( I < sizeof...(T), "Index out of bounds" );
BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
return v._get_impl( mp11::mp_size_t<I>() );
}
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
{
static_assert( I < sizeof...(T), "Index out of bounds" );
BOOST_VARIANT2_CX14_ASSERT( v.index() == I )
return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
}
} // namespace detail
// get (type)
template<class U, class... T> constexpr U& get(variant<T...>& v)
@ -520,11 +548,11 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_false, T1, T.
T1 first_;
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
{
}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
{
}
@ -564,18 +592,18 @@ template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, c
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
~variant_storage_impl()
{
@ -637,11 +665,11 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T..
T1 first_;
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): first_( std::forward<A>(a)... )
{
}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-1>(), std::forward<A>(a)... )
{
}
@ -687,18 +715,18 @@ template<class T0, class T1, class T2, class T3, class T4, class T5, class T6, c
variant_storage<T...> rest_;
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<0>, A&&... a ): t0_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<1>, A&&... a ): t1_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<2>, A&&... a ): t2_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<3>, A&&... a ): t3_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<4>, A&&... a ): t4_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<5>, A&&... a ): t5_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<6>, A&&... a ): t6_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<7>, A&&... a ): t7_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<8>, A&&... a ): t8_( std::forward<A>(a)... ) {}
template<class... A> constexpr variant_storage_impl( mp11::mp_size_t<9>, A&&... a ): t9_( std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr explicit variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<std::size_t I, class... A> constexpr variant_storage_impl( mp11::mp_size_t<I>, A&&... a ): rest_( mp11::mp_size_t<I-10>(), std::forward<A>(a)... ) {}
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<0>, A&&... a ) { ::new( &t0_ ) T0( std::forward<A>(a)... ); }
template<class... A> void emplace_impl( mp11::mp_false, mp11::mp_size_t<1>, A&&... a ) { ::new( &t1_ ) T1( std::forward<A>(a)... ); }
@ -814,21 +842,21 @@ struct none {};
// trivially destructible, single buffered
template<class... T> struct variant_base_impl<true, true, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st_;
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): st_( mp11::mp_size_t<0>() ), ix_( 0 )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), ix_( I::value + 1 )
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
}
@ -841,24 +869,25 @@ template<class... T> struct variant_base_impl<true, true, T...>
{
size_t const J = I+1;
assert( ix_ == J );
BOOST_ASSERT( ix_ == J );
return st1_.get( mp11::mp_size_t<J>() );
return st_.get( mp11::mp_size_t<J>() );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
// size_t const J = I+1;
// assert( ix_ == I+1 );
return st1_.get( mp11::mp_size_t<I+1>() );
BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
return st_.get( mp11::mp_size_t<I+1>() );
}
template<std::size_t J, class U, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, A&&... a )
{
static_assert( std::is_nothrow_constructible<U, A&&...>::value, "Logic error: U must be nothrow constructible from A&&..." );
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
st_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J;
}
@ -868,7 +897,7 @@ template<class... T> struct variant_base_impl<true, true, T...>
U tmp( std::forward<A>(a)... );
st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
ix_ = J;
}
@ -884,84 +913,79 @@ template<class... T> struct variant_base_impl<true, true, T...>
// trivially destructible, double buffered
template<class... T> struct variant_base_impl<true, false, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st2_;
variant_storage<none, T...> st_[ 2 ];
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }, ix_( 0 )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }, ix_( ( I::value + 1 ) * 2 )
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
::new( &st_[ 0 ] ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = ( I::value + 1 ) * 2;
}
constexpr std::size_t index() const noexcept
{
return ix_ >= 0? ix_ - 1: -ix_ - 1;
return ix_ / 2 - 1;
}
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{
BOOST_ASSERT( index() == I );
size_t const J = I+1;
assert( ix_ == J || -ix_ == J );
constexpr mp11::mp_size_t<J> j{};
return ix_ >= 0? st1_.get( j ): st2_.get( j );
return st_[ ix_ & 1 ].get( j );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
BOOST_VARIANT2_CX14_ASSERT( index() == I )
// size_t const J = I+1;
// assert( ix_ == J || -ix_ == J );
// constexpr mp_size_t<J> j{};
return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
return st_[ ix_ & 1 ].get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( A&&... a )
{
size_t const J = I+1;
if( ix_ >= 0 )
{
st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = -static_cast<int>( J );
}
else
{
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J;
}
unsigned i2 = 1 - ( ix_ & 1 );
st_[ i2 ].emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
ix_ = J * 2 + i2;
}
};
// not trivially destructible, single buffered
template<class... T> struct variant_base_impl<false, true, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st_;
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() )
constexpr variant_base_impl(): st_( mp11::mp_size_t<0>() ), ix_( 0 )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), ix_( I::value + 1 )
{
}
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
::new( &st_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
}
@ -977,7 +1001,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st1_.get( I() ).~U();
this_->st_.get( I() ).~U();
}
};
@ -1003,17 +1027,18 @@ template<class... T> struct variant_base_impl<false, true, T...>
{
size_t const J = I+1;
assert( ix_ == J );
BOOST_ASSERT( ix_ == J );
return st1_.get( mp11::mp_size_t<J>() );
return st_.get( mp11::mp_size_t<J>() );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
// size_t const J = I+1;
// assert( ix_ == J );
return st1_.get( mp11::mp_size_t<I+1>() );
BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
return st_.get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> void emplace( A&&... a )
@ -1028,7 +1053,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
_destroy();
st1_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
ix_ = J;
}
};
@ -1036,23 +1061,61 @@ template<class... T> struct variant_base_impl<false, true, T...>
// not trivially destructible, double buffered
template<class... T> struct variant_base_impl<false, false, T...>
{
int ix_;
variant_storage<none, T...> st1_;
variant_storage<none, T...> st2_;
#if defined(__GNUC__) && __GNUC__ < 11 && !defined(__clang__) && !defined(__INTEL_COMPILER)
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() )
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 :-(
variant_storage<none, T...> st1_, st2_;
unsigned ix_;
constexpr variant_base_impl(): st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() ), ix_( 0 )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): ix_( I::value + 1 ), st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() )
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st1_( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... ), st2_( mp11::mp_size_t<0>() ), ix_( ( I::value + 1 ) * 2 )
{
}
BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
{
return i2 == 0? st1_: st2_;
}
constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
{
return i2 == 0? st1_: st2_;
}
#else
variant_storage<none, T...> st_[ 2 ];
unsigned ix_;
constexpr variant_base_impl(): st_{ { mp11::mp_size_t<0>() }, { mp11::mp_size_t<0>() } }, ix_( 0 )
{
}
template<class I, class... A> constexpr explicit variant_base_impl( I, A&&... a ): st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { mp11::mp_size_t<0>() } }, ix_( ( I::value + 1 ) * 2 )
{
}
BOOST_CXX14_CONSTEXPR variant_storage<none, T...>& storage( unsigned i2 ) noexcept
{
return st_[ i2 ];
}
constexpr variant_storage<none, T...> const& storage( unsigned i2 ) const noexcept
{
return st_[ i2 ];
}
#endif
// requires: ix_ == 0
template<class I, class... A> void _replace( I, A&&... a )
{
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = I::value + 1;
::new( &storage( 0 ) ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
ix_ = ( I::value + 1 ) * 2;
}
//[&]( auto I ){
@ -1063,35 +1126,18 @@ template<class... T> struct variant_base_impl<false, false, T...>
struct _destroy_L1
{
variant_base_impl * this_;
unsigned i2_;
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st1_.get( I() ).~U();
}
};
struct _destroy_L2
{
variant_base_impl * this_;
template<class I> void operator()( I ) const noexcept
{
using U = mp11::mp_at<mp11::mp_list<none, T...>, I>;
this_->st2_.get( I() ).~U();
this_->storage( i2_ ).get( I() ).~U();
}
};
void _destroy() noexcept
{
if( ix_ > 0 )
{
mp11::mp_with_index<1 + sizeof...(T)>( ix_, _destroy_L1{ this } );
}
else if( ix_ < 0 )
{
mp11::mp_with_index<1 + sizeof...(T)>( -ix_, _destroy_L2{ this } );
}
mp11::mp_with_index<1 + sizeof...(T)>( ix_ / 2, _destroy_L1{ this, ix_ & 1 } );
}
~variant_base_impl() noexcept
@ -1101,46 +1147,39 @@ template<class... T> struct variant_base_impl<false, false, T...>
constexpr std::size_t index() const noexcept
{
return ix_ >= 0? ix_ - 1: -ix_ - 1;
return ix_ / 2 - 1;
}
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{
BOOST_ASSERT( index() == I );
size_t const J = I+1;
assert( ix_ == J || -ix_ == J );
constexpr mp11::mp_size_t<J> j{};
return ix_ >= 0? st1_.get( j ): st2_.get( j );
return storage( ix_ & 1 ).get( j );
}
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{
BOOST_VARIANT2_CX14_ASSERT( index() == I )
// size_t const J = I+1;
// assert( ix_ == J || -ix_ == J );
// constexpr mp_size_t<J> j{};
return ix_ >= 0? st1_.get( mp11::mp_size_t<I+1>() ): st2_.get( mp11::mp_size_t<I+1>() );
return storage( ix_ & 1 ).get( mp11::mp_size_t<I+1>() );
}
template<std::size_t I, class... A> void emplace( A&&... a )
{
size_t const J = I+1;
if( ix_ >= 0 )
{
st2_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
unsigned i2 = 1 - ( ix_ & 1 );
storage( i2 ).emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
_destroy();
ix_ = -static_cast<int>( J );
}
else
{
st1_.emplace( mp11::mp_size_t<J>(), std::forward<A>(a)... );
_destroy();
ix_ = J;
}
ix_ = J * 2 + i2;
}
};
@ -1561,7 +1600,7 @@ public:
template<class U,
class Ud = typename std::decay<U>::type,
class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
class E1 = typename std::enable_if< !std::is_same<Ud, variant>::value && !std::is_base_of<variant, Ud>::value && !detail::is_in_place_index<Ud>::value && !detail::is_in_place_type<Ud>::value >::type,
class V = detail::resolve_overload_type<U&&, T...>,
class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
>
@ -2153,7 +2192,7 @@ template<class R = detail::deduced, class F, class V1, class V2, class... V> con
{
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)... ); };
auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
});
@ -2170,36 +2209,133 @@ void swap( variant<T...> & v, variant<T...> & w )
v.swap( w );
}
// visit_by_index
namespace detail
{
template<class R, class V, class... F> using Vret2 = mp11::mp_eval_if_not< std::is_same<R, deduced>, R, front_if_same, mp11::mp_transform<mp11::mp_invoke_q, mp11::mp_list<Qret<F>...>, apply_cv_ref<V>> >;
template<class R, class V, class... F> struct visit_by_index_L
{
V&& v;
std::tuple<F&&...> tp;
template<class I> constexpr detail::Vret2<R, V, F...> operator()( I ) const
{
return std::get<I::value>( std::move(tp) )( unsafe_get<I::value>( std::forward<V>(v) ) );
}
};
} // namespace detail
template<class R = detail::deduced, class V, class... F> constexpr auto visit_by_index( V&& v, F&&... f ) -> detail::Vret2<R, V, F...>
{
static_assert( variant_size<V>::value == sizeof...(F), "Incorrect number of function objects" );
return mp11::mp_with_index<variant_size<V>::value>( v.index(),
detail::visit_by_index_L<R, V, F...>{ std::forward<V>(v), std::tuple<F&&...>( std::forward<F>(f)... ) } );
}
// output streaming
namespace detail
{
template<class Ch, class Tr, class... T> struct ostream_insert_L
{
std::basic_ostream<Ch, Tr>& os;
variant<T...> const& v;
template<class I> std::basic_ostream<Ch, Tr>& operator()( I ) const
{
return os << unsafe_get<I::value>( v );
}
};
template<class Os, class T, class E = void> struct is_output_streamable: std::false_type
{
};
template<class Os, class T> struct is_output_streamable<Os, T, decltype( std::declval<Os&>() << std::declval<T const&>(), (void)0 )>: std::true_type
{
};
} // namespace detail
template<class Ch, class Tr>
std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, monostate const& )
{
os << "monostate";
return os;
}
template<class Ch, class Tr, class T1, class... T,
class E = typename std::enable_if< mp11::mp_all< detail::is_output_streamable<std::basic_ostream<Ch, Tr>, T>... >::value >::type >
std::basic_ostream<Ch, Tr>& operator<<( std::basic_ostream<Ch, Tr>& os, variant<T1, T...> const& v )
{
return mp11::mp_with_index<1 + sizeof...(T)>( v.index(),
detail::ostream_insert_L<Ch, Tr, T1, T...>{ os, v } );
}
// hashing support
namespace detail
{
template<class V> struct hash_value_L
inline std::size_t hash_value_impl_( mp11::mp_true, std::size_t index, std::size_t value )
{
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;
hv ^= index;
hv *= prime;
hv ^= value;
hv *= prime;
return static_cast<std::size_t>( hv );
}
inline std::size_t hash_value_impl_( mp11::mp_false, std::size_t index, std::size_t value )
{
std::size_t hv = 0x811C9DC5;
std::size_t const prime = 0x01000193;
hv ^= index;
hv *= prime;
hv ^= value;
hv *= prime;
return hv;
}
inline std::size_t hash_value_impl( std::size_t index, std::size_t value )
{
return hash_value_impl_( mp11::mp_bool< (SIZE_MAX > UINT32_MAX) >(), index, value );
}
template<template<class> class H, 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;
std::size_t index = I::value;
std::size_t value = H<remove_cv_ref_t<decltype(t)>>()( t );
return static_cast<std::size_t>( hv );
return hash_value_impl( index, value );
}
};
template<class... T> std::size_t hash_value_std( variant<T...> const & v )
{
return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< std::hash, variant<T...> >{ v } );
}
} // namespace detail
inline std::size_t hash_value( monostate const & )
@ -2209,7 +2345,7 @@ inline std::size_t hash_value( monostate const & )
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 } );
return mp11::mp_with_index<sizeof...(T)>( v.index(), detail::hash_value_L< boost::hash, variant<T...> >{ v } );
}
namespace detail
@ -2230,7 +2366,7 @@ template<class V> struct std_hash_impl<V, true>
{
std::size_t operator()( V const & v ) const
{
return hash_value( v );
return detail::hash_value_std( v );
}
};
@ -2256,6 +2392,8 @@ template<> struct hash< ::boost::variant2::monostate >
} // namespace std
#undef BOOST_VARIANT2_CX14_ASSERT
#if defined(_MSC_VER) && _MSC_VER < 1910
# pragma warning( pop )
#endif

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

@ -115,4 +115,14 @@ run variant_visit_derived.cpp ;
run variant_many_types.cpp ;
run variant_visit_r.cpp ;
run variant_visit_r.cpp : : :
<toolset>gcc,<target-os>windows:<variant>release
<toolset>gcc,<target-os>cygwin:<variant>release
;
compile variant_derived_construct.cpp ;
run variant_visit_by_index.cpp ;
run variant_ostream_insert.cpp ;
run is_output_streamable.cpp ;

View File

@ -7,6 +7,8 @@ cmake_minimum_required(VERSION 3.5...3.16)
project(cmake_subdir_test LANGUAGES CXX)
add_subdirectory(../.. boostorg/variant2)
add_subdirectory(../../../assert boostorg/assert)
add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../mp11 boostorg/mp11)

View File

@ -0,0 +1,41 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <ostream>
#include <string>
struct X
{
};
struct Y
{
};
std::ostream& operator<<( std::ostream& os, Y const& /*y*/ )
{
os << "Y()";
return os;
}
int main()
{
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, int>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, float>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, std::string>));
BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable<std::ostream, void>));
BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable<std::ostream, X>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, Y>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, boost::variant2::monostate>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, boost::variant2::variant<int, float, std::string>>));
BOOST_TEST_TRAIT_FALSE((boost::variant2::detail::is_output_streamable<std::ostream, boost::variant2::variant<int, float, X>>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, boost::variant2::variant<int, float, Y>>));
BOOST_TEST_TRAIT_TRUE((boost::variant2::detail::is_output_streamable<std::ostream, boost::variant2::variant<boost::variant2::monostate, int, float>>));
return boost::report_errors();
}

View File

@ -1,10 +1,8 @@
// Copyright 2019 Peter Dimov.
//
// Distributed under the Boost Software License, Version 1.0.
// http://www.boost.org/LICENSE_1_0.txt
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/variant2.hpp>
using namespace boost::variant2;

View File

@ -0,0 +1,33 @@
// Copyright 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
using namespace boost::variant2;
template<class... T> class X: variant<T...>
{
using base = variant<T...>;
using base::base;
};
struct Y
{
Y( Y const& rhs ) = default;
template<class T> Y( T const& t )
{
t.bar();
}
};
int main()
{
using W = X<int, double, Y>;
W a( 1 );
W b( a );
(void)b;
}

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

@ -88,5 +88,12 @@ int main()
BOOST_TEST_NOT( v1 != v2 );
}
{
variant<monostate> v1, v2;
BOOST_TEST( v1 == v2 );
BOOST_TEST_NOT( v1 != v2 );
}
return boost::report_errors();
}

View File

@ -93,6 +93,13 @@ int main()
STATIC_ASSERT( !(v1 == v2) );
STATIC_ASSERT( !(v1 != v2) );
}
{
constexpr variant<monostate> v1, v2;
STATIC_ASSERT( v1 == v2 );
STATIC_ASSERT( !(v1 != v2) );
}
}
#endif

View File

@ -12,6 +12,7 @@
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/container_hash/hash.hpp>
#include <boost/config/workaround.hpp>
#include <vector>
using namespace boost::variant2;
@ -47,7 +48,17 @@ template<template<class...> class Hash, class T> void test2()
BOOST_TEST_NE( h2, h3 );
}
struct X {};
struct X
{
int m = 0;
};
std::size_t hash_value( X const& x )
{
return boost::hash<int>()( x.m );
}
struct Y {}; // no hash support
int main()
{
@ -57,6 +68,8 @@ int main()
test<boost::hash, monostate, monostate, monostate>();
test<boost::hash, int, int, float>();
test<boost::hash, monostate, X, std::vector<X>>();
test2<std::hash, int>();
test2<std::hash, float>();
@ -65,7 +78,7 @@ int main()
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1910) && ( !defined(_LIBCPP_STD_VER) || _LIBCPP_STD_VER > 11 )
BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled<X> ));
BOOST_TEST_TRAIT_FALSE(( detail::is_hash_enabled<Y> ));
#endif

View File

@ -105,9 +105,9 @@ int main()
STATIC_ASSERT( v.index() == 4 );
}
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 100200)
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 120000)
// no idea why this fails on g++ 10
// no idea why this fails on g++ 10/11
#else

View File

@ -102,9 +102,9 @@ int main()
STATIC_ASSERT( holds_alternative<X>(v) );
}
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 100200)
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 120000)
// no idea why this fails on g++ 10
// no idea why this fails on g++ 10/11
#else

View File

@ -81,5 +81,14 @@ int main()
BOOST_TEST_NOT( v1 >= v2 );
}
{
variant<monostate> v1, v2;
BOOST_TEST_NOT( v1 < v2 );
BOOST_TEST_NOT( v1 > v2 );
BOOST_TEST( v1 <= v2 );
BOOST_TEST( v1 >= v2 );
}
return boost::report_errors();
}

View File

@ -86,6 +86,15 @@ int main()
STATIC_ASSERT( !(v1 <= v2) );
STATIC_ASSERT( !(v1 >= v2) );
}
{
constexpr variant<monostate> v1, v2;
STATIC_ASSERT( !(v1 < v2) );
STATIC_ASSERT( !(v1 > v2) );
STATIC_ASSERT( v1 <= v2 );
STATIC_ASSERT( v1 >= v2 );
}
}
#endif

View File

@ -0,0 +1,43 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <sstream>
#include <string>
using namespace boost::variant2;
template<class T> std::string to_string( T const& t )
{
std::ostringstream os;
os << t;
return os.str();
}
int main()
{
{
BOOST_TEST_EQ( to_string( monostate() ), "monostate" );
}
{
variant<monostate, int, float, std::string> v;
BOOST_TEST_EQ( to_string( v ), to_string( monostate() ) );
v = 1;
BOOST_TEST_EQ( to_string( v ), to_string( 1 ) );
v = 3.14f;
BOOST_TEST_EQ( to_string( v ), to_string( 3.14f ) );
v = "test";
BOOST_TEST_EQ( to_string( v ), to_string( "test" ) );
}
return boost::report_errors();
}

View File

@ -0,0 +1,126 @@
// Copyright 2017, 2021 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://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 <boost/mp11.hpp>
#include <boost/config.hpp>
using namespace boost::variant2;
using boost::mp11::mp_int;
struct X
{
};
struct F1
{
int operator()( X& ) const { return 1; }
int operator()( X const& ) const { return 2; }
int operator()( X&& ) const { return 3; }
int operator()( X const&& ) const { return 4; }
};
struct F2
{
mp_int<1> operator()( X& ) const { return {}; }
mp_int<2> operator()( X const& ) const { return {}; }
mp_int<3> operator()( X&& ) const { return {}; }
mp_int<4> operator()( X const&& ) const { return {}; }
};
int main()
{
{
variant<int, int, float> v;
visit_by_index( v,
[]( int& x ){ BOOST_TEST_EQ( x, 0 ); },
[]( int& ){ BOOST_ERROR( "incorrect alternative" ); },
[]( float& ){ BOOST_ERROR( "incorrect alternative" ); } );
}
{
variant<int const, int, float const> v( in_place_index_t<0>(), 1 );
visit_by_index( v,
[]( int const& x ){ BOOST_TEST_EQ( x, 1 ); },
[]( int& ){ BOOST_ERROR( "incorrect alternative" ); },
[]( float const& ){ BOOST_ERROR( "incorrect alternative" ); } );
}
{
variant<int, int, float> const v( in_place_index_t<1>(), 2 );
visit_by_index( v,
[]( int const& ){ BOOST_ERROR( "incorrect alternative" ); },
[]( int const& x ){ BOOST_TEST_EQ( x, 2 ); },
[]( float const& ){ BOOST_ERROR( "incorrect alternative" ); } );
}
{
variant<int const, int, float const> const v( 3.14f );
visit_by_index( v,
[]( int const& ){ BOOST_ERROR( "incorrect alternative" ); },
[]( int const& ){ BOOST_ERROR( "incorrect alternative" ); },
[]( float const& x ){ BOOST_TEST_EQ( x, 3.14f ); } );
}
{
variant<int, float> const v( 7 );
auto r = visit_by_index( v,
[]( int const& x ) -> double { return x; },
[]( float const& x ) -> double { return x; } );
BOOST_TEST_TRAIT_SAME( decltype(r), double );
BOOST_TEST_EQ( r, 7.0 );
}
{
variant<int, float> const v( 2.0f );
auto r = visit_by_index( v,
[]( int const& x ) { return x + 0.0; },
[]( float const& x ) { return x + 0.0; } );
BOOST_TEST_TRAIT_SAME( decltype(r), double );
BOOST_TEST_EQ( r, 2.0 );
}
{
variant<int, float, double> const v( 3.0 );
auto r = visit_by_index<double>( v,
[]( int const& x ) { return x; },
[]( float const& x ) { return x; },
[]( double const& x ) { return x; } );
BOOST_TEST_TRAIT_SAME( decltype(r), double );
BOOST_TEST_EQ( r, 3.0 );
}
{
variant<X> v;
variant<X> const cv;
F1 f1;
BOOST_TEST_EQ( visit_by_index( v, f1 ), 1 );
BOOST_TEST_EQ( visit_by_index( cv, f1 ), 2 );
BOOST_TEST_EQ( visit_by_index( std::move( v ), f1 ), 3 );
BOOST_TEST_EQ( visit_by_index( std::move( cv ), f1 ), 4 );
F2 f2;
BOOST_TEST_EQ( visit_by_index<int>( v, f2 ), 1 );
BOOST_TEST_EQ( visit_by_index<int>( cv, f2 ), 2 );
BOOST_TEST_EQ( visit_by_index<int>( std::move( v ), f2 ), 3 );
BOOST_TEST_EQ( visit_by_index<int>( std::move( cv ), f2 ), 4 );
}
return boost::report_errors();
}

View File

@ -1,4 +1,3 @@
// Copyright 2017, 2020 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
@ -15,7 +14,7 @@
struct X: boost::variant2::variant<int, float>
{
#if BOOST_WORKAROUND( BOOST_MSVC, < 1930 )
#if BOOST_WORKAROUND( BOOST_MSVC, < 1940 )
template<class T> explicit X( T&& t ): variant( std::forward<T>( t ) ) {};