Compare commits

...

78 Commits

Author SHA1 Message Date
f9bdafd3ca Remove C++11 requirements from test/Jamfile 2024-05-18 03:18:56 +03:00
38293da18e Update .drone.jsonnet 2024-05-18 02:43:52 +03:00
65ab0f8cef Update ci.yml 2024-05-17 22:04:55 +03:00
78796d0e7d Increase workaround to < 1950, because VS2022 has reached _MSC_VER=1940. Refs #43. 2024-05-17 21:44:21 +03:00
ff36c3aa1f Merge pull request #42 from K-ballo/more-natvis
Improve natvis
2024-03-25 02:22:20 +02:00
f0acc9326e Work around MSVC failures in variant_derived_construct2. Refs #43. 2024-03-24 19:16:09 +02:00
a936eae01b Add test/variant_derived_construct2. Refs #43. 2024-03-24 18:41:49 +02:00
77234b514c Improve natvis:
- extend support from 10 to 40 alternatives,
- split single-buffer vs double-buffer definitions,
- adjust display string to follow MS definition for std::variant
2024-03-23 16:04:54 -03:00
c125b32938 Add msvc-14.3 /permissive- to Drone 2024-02-08 20:58:45 +02:00
3298078c8b Update .drone.jsonnet 2024-01-11 22:05:28 +02:00
a38839febc Update ci.yml 2024-01-11 21:20:40 +02:00
c3071b7d0b Merge pull request #40 from Lastique/patch-1
Add missing dots in visit_by_index docs
2024-01-11 21:03:37 +02:00
9cf32980a9 Add missing dots in visit_by_index docs 2024-01-11 20:18:06 +03:00
9e4234bfd5 Merge pull request #39 from 13steinj/develop
Suppress -Wuninitialized in emplace_impl
2023-10-24 12:42:10 +03:00
55f1332ce0 Suppress -Wuninitialized in emplace_impl
Closes #38
2023-10-23 15:46:15 -05:00
db12c36b89 Remove unnecessary includes 2023-10-11 18:28:11 +03:00
a5cb0582d5 Make tag_invoke_L2 more msvc-14.0-friendly 2023-09-03 18:28:49 +03:00
e2546b70ca Document uses_double_storage(). Refs #37. 2023-06-29 18:32:58 +03:00
362224a009 Update ci.yml 2023-06-29 16:44:47 +03:00
2c590716ab Use the exact 3.125f in variant_visit_r.cpp 2023-06-29 12:05:55 +03:00
82b98fb757 Cast 3.14f to float because FLT_EVAL_METHOD (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108742) for discussion 2023-06-29 10:46:54 +03:00
30afb9e183 Update test/Jamfile to fix Drone issues 2023-06-29 09:54:49 +03:00
129e27ce09 Update Drone files 2023-06-29 09:33:44 +03:00
26595285d3 Add variant<>::uses_double_storage(). Refs #37. 2023-06-28 22:14:56 +03:00
95a8c5ffec Update .drone.jsonnet 2023-01-23 03:53:25 +02:00
ec2819a05e Update CMakeLists.txt 2023-01-13 00:56:45 +02:00
fcf9746a2d Merge branch 'develop' of https://github.com/vinniefalco/boost-variant2 into feature/pr-36 2023-01-13 00:55:17 +02:00
a74ebd34dc Update appveyor.yml 2023-01-12 21:12:17 +02:00
1b34c20685 Update appveyor.yml 2023-01-12 18:38:10 +02:00
604d3700ad Add CMake tests to Appveyor 2023-01-12 10:49:41 +02:00
4d1fd43d72 Update supported compilers in documentation and README 2022-10-27 21:25:57 +03:00
376925a209 Work around msvc-14.1 /permissive- failure 2022-10-24 15:47:09 +03:00
bcb8796225 Add /permissive- jobs to Drone and Appveyor 2022-10-24 15:27:05 +03:00
a948b85c74 Update revision history 2022-10-18 17:38:59 +03:00
32862d6db7 Add missing std::move 2022-10-18 16:02:33 +03:00
423d350ff1 Remove unneeded forward declarations 2022-10-18 16:01:31 +03:00
aad1f86fae Reflect the change in is_null_like 2022-10-18 16:00:14 +03:00
1f8c4a1900 Replace polymorphic lambdas with function objects for C++11 2022-10-18 06:29:57 +03:00
67a12199e6 Add JSON support (refs #28) 2022-10-18 06:08:18 +03:00
457147d1b0 Suppress -Wmaybe-uninitialized in emplace_impl 2022-10-18 03:20:36 +03:00
4a5f3dc498 Add variant<monostate, T>::emplace tests to fish out -Wmaybe-uninitialized warnings 2022-10-18 02:56:15 +03:00
6fe1c69bc8 Add Drone support 2022-10-18 02:16:59 +03:00
78a974429a Update ci.yml 2022-10-15 19:39:32 +03:00
4c5f254b9c add boost_variant2.natvis and interface source files 2022-08-19 12:13:08 -07:00
c633a953de Change macos-10.15 to macos-11 in ci.yml 2022-08-15 19:26:35 +03:00
8ee7c5aad0 Update ci.yml 2022-07-14 14:47:06 +03: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
33 changed files with 2135 additions and 171 deletions

438
.drone.jsonnet Normal file
View File

@ -0,0 +1,438 @@
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
local library = "variant2";
local triggers =
{
branch: [ "master", "develop", "feature/*" ]
};
local ubsan = { UBSAN: '1', UBSAN_OPTIONS: 'print_stacktrace=1' };
local asan = { ASAN: '1' };
local linux_pipeline(name, image, environment, packages = "", sources = [], arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "linux",
arch: arch
},
steps:
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'set -e',
'wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add -',
] +
(if sources != [] then [ ('apt-add-repository "' + source + '"') for source in sources ] else []) +
(if packages != "" then [ 'apt-get update', 'apt-get -y install ' + packages ] else []) +
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local macos_pipeline(name, environment, xcode_version = "12.2", osx_version = "catalina", arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "exec",
trigger: triggers,
platform: {
"os": "darwin",
"arch": arch
},
node: {
"os": osx_version
},
steps: [
{
name: "everything",
environment: environment + { "DEVELOPER_DIR": "/Applications/Xcode-" + xcode_version + ".app/Contents/Developer" },
commands:
[
'export LIBRARY=' + library,
'./.drone/drone.sh',
]
}
]
};
local windows_pipeline(name, image, environment, arch = "amd64") =
{
name: name,
kind: "pipeline",
type: "docker",
trigger: triggers,
platform:
{
os: "windows",
arch: arch
},
"steps":
[
{
name: "everything",
image: image,
environment: environment,
commands:
[
'cmd /C .drone\\\\drone.bat ' + library,
]
}
]
};
[
linux_pipeline(
"Linux 16.04 GCC 4.8 32/64",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11', ADDRMD: '32,64' },
"g++-4.8-multilib",
),
linux_pipeline(
"Linux 16.04 GCC 4.9 32/64",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-4.9', CXXSTD: '11', ADDRMD: '32,64' },
"g++-4.9-multilib",
),
linux_pipeline(
"Linux 16.04 GCC 5* 32/64",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 6 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-6', CXXSTD: '11,14', ADDRMD: '32,64' },
"g++-6-multilib",
),
linux_pipeline(
"Linux 18.04 GCC 7* 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 18.04 GCC 8 32/64",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-8', CXXSTD: '11,14,17', ADDRMD: '32,64' },
"g++-8-multilib",
),
linux_pipeline(
"Linux 20.04 GCC 9* 32/64",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 20.04 GCC 9* ARM64",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
arch="arm64",
),
linux_pipeline(
"Linux 20.04 GCC 9* S390x",
"cppalliance/droneubuntu2004:multiarch",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a' },
arch="s390x",
),
linux_pipeline(
"Linux 20.04 GCC 10 32/64",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-10', CXXSTD: '11,14,17,20', ADDRMD: '32,64' },
"g++-10-multilib",
),
linux_pipeline(
"Linux 22.04 GCC 11* 32/64",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++', CXXSTD: '11,14,17,2a', ADDRMD: '32,64' },
),
linux_pipeline(
"Linux 22.04 GCC 12 32/64",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-12', CXXSTD: '11,14,17,20,2b', ADDRMD: '32,64' },
"g++-12-multilib",
),
linux_pipeline(
"Linux 23.04 GCC 13 32 ASAN",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + asan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 23.04 GCC 13 64 ASAN",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + asan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 23.04 GCC 13 32 UBSAN",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' } + ubsan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 23.04 GCC 13 64 UBSAN",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-13', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' } + ubsan,
"g++-13-multilib",
),
linux_pipeline(
"Linux 24.04 GCC 14 32",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b', ADDRMD: '32' },
"g++-14-multilib",
),
linux_pipeline(
"Linux 24.04 GCC 14 64",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'gcc', COMPILER: 'g++-14', CXXSTD: '11,14,17,20,2b', ADDRMD: '64' },
"g++-14-multilib",
),
linux_pipeline(
"Linux 16.04 Clang 3.5",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.5', CXXSTD: '11' },
"clang-3.5",
),
linux_pipeline(
"Linux 16.04 Clang 3.6",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.6', CXXSTD: '11,14' },
"clang-3.6",
),
linux_pipeline(
"Linux 16.04 Clang 3.7",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.7', CXXSTD: '11,14' },
"clang-3.7",
),
linux_pipeline(
"Linux 16.04 Clang 3.8",
"cppalliance/droneubuntu1604:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.8', CXXSTD: '11,14' },
"clang-3.8",
),
linux_pipeline(
"Linux 18.04 Clang 3.9",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-3.9', CXXSTD: '11,14' },
"clang-3.9",
),
linux_pipeline(
"Linux 18.04 Clang 4.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-4.0', CXXSTD: '11,14' },
"clang-4.0",
),
linux_pipeline(
"Linux 18.04 Clang 5.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-5.0', CXXSTD: '11,14,1z' },
"clang-5.0",
),
linux_pipeline(
"Linux 18.04 Clang 6.0",
"cppalliance/droneubuntu1804:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-6.0', CXXSTD: '11,14,17' },
"clang-6.0",
),
linux_pipeline(
"Linux 20.04 Clang 7",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-7', CXXSTD: '11,14,17' },
"clang-7",
),
linux_pipeline(
"Linux 20.04 Clang 8",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-8', CXXSTD: '11,14,17' },
"clang-8",
),
linux_pipeline(
"Linux 20.04 Clang 9",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-9', CXXSTD: '11,14,17,2a' },
"clang-9",
),
linux_pipeline(
"Linux 20.04 Clang 10",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-10', CXXSTD: '11,14,17,2a' },
"clang-10",
),
linux_pipeline(
"Linux 20.04 Clang 11",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-11', CXXSTD: '11,14,17,2a' },
"clang-11",
),
linux_pipeline(
"Linux 20.04 Clang 12",
"cppalliance/droneubuntu2004:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-12', CXXSTD: '11,14,17,2a' },
"clang-12",
),
linux_pipeline(
"Linux 22.04 Clang 13",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-13', CXXSTD: '11,14,17,20,2b' },
"clang-13",
),
linux_pipeline(
"Linux 22.04 Clang 14",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-14', CXXSTD: '11,14,17,20,2b' },
"clang-14",
),
linux_pipeline(
"Linux 22.04 Clang 15",
"cppalliance/droneubuntu2204:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-15', CXXSTD: '11,14,17,20,2b' },
"clang-15",
),
linux_pipeline(
"Linux 23.04 Clang 16",
"cppalliance/droneubuntu2304:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-16', CXXSTD: '11,14,17,20,2b' },
"clang-16",
),
linux_pipeline(
"Linux 23.10 Clang 17 UBSAN",
"cppalliance/droneubuntu2310:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + ubsan,
"clang-17",
),
linux_pipeline(
"Linux 23.10 Clang 17 ASAN",
"cppalliance/droneubuntu2310:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-17', CXXSTD: '11,14,17,20,2b' } + asan,
"clang-17",
),
linux_pipeline(
"Linux 24.04 Clang 18 UBSAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + ubsan,
"clang-18",
),
linux_pipeline(
"Linux 24.04 Clang 18 ASAN",
"cppalliance/droneubuntu2404:1",
{ TOOLSET: 'clang', COMPILER: 'clang++-18', CXXSTD: '11,14,17,20,2b' } + asan,
"clang-18",
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + ubsan,
),
macos_pipeline(
"MacOS 10.15 Xcode 12.2 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,1z' } + asan,
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 UBSAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + ubsan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
macos_pipeline(
"MacOS 12.4 Xcode 13.4.1 ASAN",
{ TOOLSET: 'clang', COMPILER: 'clang++', CXXSTD: '11,14,17,20,2b' } + asan,
xcode_version = "13.4.1", osx_version = "monterey", arch = "arm64",
),
windows_pipeline(
"Windows VS2015 msvc-14.0",
"cppalliance/dronevs2015",
{ TOOLSET: 'msvc-14.0', CXXSTD: '14,latest', B2_DONT_EMBED_MANIFEST: '1' },
),
windows_pipeline(
"Windows VS2017 msvc-14.1",
"cppalliance/dronevs2017",
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17,latest' },
),
windows_pipeline(
"Windows VS2017 msvc-14.1 permissive-",
"cppalliance/dronevs2017",
{ TOOLSET: 'msvc-14.1', CXXSTD: '14,17', CXXFLAGS: '/permissive-' },
),
windows_pipeline(
"Windows VS2019 msvc-14.2",
"cppalliance/dronevs2019",
{ TOOLSET: 'msvc-14.2', CXXSTD: '14,17,20,latest' },
),
windows_pipeline(
"Windows VS2019 msvc-14.2 permissive-",
"cppalliance/dronevs2019",
{ TOOLSET: 'msvc-14.2', CXXSTD: '14,17', CXXFLAGS: '/permissive-' },
),
windows_pipeline(
"Windows VS2022 msvc-14.3",
"cppalliance/dronevs2022:1",
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17,20,latest' },
),
windows_pipeline(
"Windows VS2022 msvc-14.3 permissive-",
"cppalliance/dronevs2022:1",
{ TOOLSET: 'msvc-14.3', CXXSTD: '14,17', CXXFLAGS: '/permissive-' },
),
]

24
.drone/drone.bat Normal file
View File

@ -0,0 +1,24 @@
@REM Copyright 2022 Peter Dimov
@REM Distributed under the Boost Software License, Version 1.0.
@REM https://www.boost.org/LICENSE_1_0.txt
@ECHO ON
set LIBRARY=%1
set DRONE_BUILD_DIR=%CD%
set BOOST_BRANCH=develop
if "%DRONE_BRANCH%" == "master" set BOOST_BRANCH=master
cd ..
git clone -b %BOOST_BRANCH% --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
xcopy /s /e /q %DRONE_BUILD_DIR% libs\%LIBRARY%\
python tools/boostdep/depinst/depinst.py %LIBRARY%
cmd /c bootstrap
b2 -d0 headers
if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS%
b2 -j3 libs/%LIBRARY%/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker

25
.drone/drone.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
# Copyright 2022 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# https://www.boost.org/LICENSE_1_0.txt
set -ex
export PATH=~/.local/bin:/usr/local/bin:$PATH
DRONE_BUILD_DIR=$(pwd)
BOOST_BRANCH=develop
if [ "$DRONE_BRANCH" = "master" ]; then BOOST_BRANCH=master; fi
cd ..
git clone -b $BOOST_BRANCH --depth 1 https://github.com/boostorg/boost.git boost-root
cd boost-root
git submodule update --init tools/boostdep
cp -r $DRONE_BUILD_DIR/* libs/$LIBRARY
python tools/boostdep/depinst/depinst.py $LIBRARY
./bootstrap.sh
./b2 -d0 headers
echo "using $TOOLSET : : $COMPILER ;" > ~/user-config.jam
./b2 -j3 libs/$LIBRARY/test toolset=$TOOLSET cxxstd=$CXXSTD variant=debug,release ${ADDRMD:+address-model=$ADDRMD} ${UBSAN:+undefined-sanitizer=norecover debug-symbols=on} ${ASAN:+address-sanitizer=norecover debug-symbols=on} ${LINKFLAGS:+linkflags=$LINKFLAGS}

View File

@ -18,107 +18,181 @@ jobs:
matrix: matrix:
include: include:
- toolset: gcc-4.8 - toolset: gcc-4.8
cxxstd: "03,11" cxxstd: "11"
os: ubuntu-16.04 container: ubuntu:16.04
os: ubuntu-latest
install: g++-4.8 install: g++-4.8
- toolset: gcc-4.9 - toolset: gcc-4.9
cxxstd: "03,11" cxxstd: "11"
os: ubuntu-16.04 container: ubuntu:16.04
os: ubuntu-latest
install: g++-4.9 install: g++-4.9
- toolset: gcc-5 - toolset: gcc-5
cxxstd: "03,11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-16.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-5
- toolset: gcc-6 - toolset: gcc-6
cxxstd: "03,11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-16.04 container: ubuntu:18.04
os: ubuntu-latest
install: g++-6 install: g++-6
- toolset: gcc-7 - toolset: gcc-7
cxxstd: "03,11,14,17" cxxstd: "11,14,17"
os: ubuntu-18.04 container: ubuntu:18.04
os: ubuntu-latest
- toolset: gcc-8 - toolset: gcc-8
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-18.04 os: ubuntu-20.04
install: g++-8 install: g++-8
- toolset: gcc-9 - toolset: gcc-9
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-18.04 os: ubuntu-20.04
- toolset: gcc-10 - toolset: gcc-10
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-18.04 os: ubuntu-22.04
- toolset: clang install: g++-10
compiler: clang++-3.5 - toolset: gcc-11
cxxstd: "03,11,14" cxxstd: "11,14,17,2a"
os: ubuntu-16.04 os: ubuntu-22.04
install: clang-3.5 install: g++-11
- toolset: clang - toolset: gcc-12
compiler: clang++-3.6 cxxstd: "11,14,17,20,2b"
cxxstd: "03,11,14" os: ubuntu-22.04
os: ubuntu-16.04 install: g++-12
install: clang-3.6 - toolset: gcc-13
- toolset: clang cxxstd: "11,14,17,20,2b"
compiler: clang++-3.7 container: ubuntu:23.04
cxxstd: "03,11,14" os: ubuntu-latest
os: ubuntu-16.04 install: g++-13
install: clang-3.7 - toolset: gcc-14
- toolset: clang cxxstd: "11,14,17,20,2b"
compiler: clang++-3.8 container: ubuntu:24.04
cxxstd: "03,11,14" os: ubuntu-latest
os: ubuntu-16.04 install: g++-14
install: clang-3.8
- toolset: clang - toolset: clang
compiler: clang++-3.9 compiler: clang++-3.9
cxxstd: "03,11,14" cxxstd: "11,14"
os: ubuntu-16.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-3.9 install: clang-3.9
- toolset: clang - toolset: clang
compiler: clang++-4.0 compiler: clang++-4.0
cxxstd: "03,11,14" cxxstd: "11,14"
os: ubuntu-16.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-4.0 install: clang-4.0
- toolset: clang - toolset: clang
compiler: clang++-5.0 compiler: clang++-5.0
cxxstd: "03,11,14,1z" cxxstd: "11,14,1z"
os: ubuntu-16.04 container: ubuntu:18.04
os: ubuntu-latest
install: clang-5.0 install: clang-5.0
- toolset: clang - toolset: clang
compiler: clang++-6.0 compiler: clang++-6.0
cxxstd: "03,11,14,17" cxxstd: "11,14,17"
os: ubuntu-18.04 os: ubuntu-20.04
install: clang-6.0 install: clang-6.0
- toolset: clang - toolset: clang
compiler: clang++-7 compiler: clang++-7
cxxstd: "03,11,14,17" cxxstd: "11,14,17"
os: ubuntu-18.04 os: ubuntu-20.04
install: clang-7 install: clang-7
- toolset: clang - toolset: clang
compiler: clang++-8 compiler: clang++-8
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17"
os: ubuntu-20.04 os: ubuntu-20.04
install: clang-8 install: clang-8
- toolset: clang - toolset: clang
compiler: clang++-9 compiler: clang++-9
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 os: ubuntu-20.04
install: clang-9
- toolset: clang - toolset: clang
compiler: clang++-10 compiler: clang++-10
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 os: ubuntu-20.04
install: clang-10
- toolset: clang - toolset: clang
compiler: clang++-11 compiler: clang++-11
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
os: ubuntu-20.04 os: ubuntu-20.04
install: clang-11
- toolset: clang - toolset: clang
cxxstd: "03,11,14,17,2a" compiler: clang++-12
os: macos-10.15 cxxstd: "11,14,17,2a"
os: ubuntu-20.04
install: clang-12
- toolset: clang
compiler: clang++-13
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-13
- toolset: clang
compiler: clang++-14
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-14
- toolset: clang
compiler: clang++-15
cxxstd: "11,14,17,20,2b"
container: ubuntu:22.04
os: ubuntu-latest
install: clang-15
- toolset: clang
compiler: clang++-16
cxxstd: "11,14,17,20,2b"
container: ubuntu:23.04
os: ubuntu-latest
install: clang-16
- toolset: clang
compiler: clang++-17
cxxstd: "11,14,17,20,2b"
container: ubuntu:23.10
os: ubuntu-latest
install: clang-17
- toolset: clang
compiler: clang++-18
cxxstd: "11,14,17,20,2b"
container: ubuntu:24.04
os: ubuntu-latest
install: clang-18
- toolset: clang
cxxstd: "11,14,17,2a"
os: macos-11
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-12
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-13
- toolset: clang
cxxstd: "11,14,17,20,2b"
os: macos-14
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
container: ${{matrix.container}}
defaults:
run:
shell: bash
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- name: Setup container environment
if: matrix.container
run: |
apt-get update
apt-get -y install sudo python3 git g++
- name: Install packages - name: Install packages
if: matrix.install if: matrix.install
run: sudo apt install ${{matrix.install}} run: |
sudo apt-get update
sudo apt-get -y install ${{matrix.install}}
- name: Setup Boost - name: Setup Boost
run: | run: |
@ -138,7 +212,7 @@ jobs:
cd boost-root cd boost-root
cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY
git submodule update --init tools/boostdep git submodule update --init tools/boostdep
python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY python3 tools/boostdep/depinst/depinst.py $LIBRARY
./bootstrap.sh ./bootstrap.sh
./b2 -d0 headers ./b2 -d0 headers
@ -157,23 +231,31 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
include: include:
- toolset: msvc-14.1 - toolset: msvc-14.0
cxxstd: "14,17,latest" cxxstd: "14,latest"
addrmd: 32,64
os: windows-2016
- toolset: msvc-14.2
cxxstd: "14,17,latest"
addrmd: 32,64 addrmd: 32,64
os: windows-2019 os: windows-2019
- toolset: msvc-14.2
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2019
- toolset: msvc-14.3
cxxstd: "14,17,20,latest"
addrmd: 32,64
os: windows-2022
- toolset: clang-win
cxxstd: "14,17,latest"
addrmd: 32,64
os: windows-2022
- toolset: gcc - toolset: gcc
cxxstd: "03,11,14,17,2a" cxxstd: "11,14,17,2a"
addrmd: 64 addrmd: 64
os: windows-2019 os: windows-2019
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
- name: Setup Boost - name: Setup Boost
shell: cmd shell: cmd
@ -201,4 +283,346 @@ jobs:
shell: cmd shell: cmd
run: | run: |
cd ../boost-root cd ../boost-root
b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release b2 -j3 libs/%LIBRARY%/test toolset=${{matrix.toolset}} cxxstd=${{matrix.cxxstd}} address-model=${{matrix.addrmd}} variant=debug,release embed-manifest-via=linker
posix-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt-get -y 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-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt-get -y 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-20.04
- os: ubuntu-22.04
- os: macos-11
- os: macos-12
- os: macos-13
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- name: Install packages
if: matrix.install
run: sudo apt-get -y 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
windows-cmake-subdir:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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%
- name: Use library with add_subdirectory (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test
mkdir __build__ && cd __build__
cmake ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use library with add_subdirectory (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_subdir_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-install:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
- name: Install (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Debug
- name: Install (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target install --config Release
- name: Use the installed library (Debug)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test && mkdir __build__ && cd __build__
cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
cmake --build . --config Debug
ctest --output-on-failure --no-tests=error -C Debug
- name: Use the installed library (Release)
shell: cmd
run: |
cd ../boost-root/libs/%LIBRARY%/test/cmake_install_test/__build__
cmake --build . --config Release
ctest --output-on-failure --no-tests=error -C Release
windows-cmake-test:
strategy:
fail-fast: false
matrix:
include:
- os: windows-2019
- os: windows-2022
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v4
- 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%
- name: Configure
shell: cmd
run: |
cd ../boost-root
mkdir __build__ && cd __build__
cmake -DBOOST_INCLUDE_LIBRARIES=%LIBRARY% -DBUILD_TESTING=ON ..
- name: Build tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Debug
- name: Run tests (Debug)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Debug
- name: Build tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
cmake --build . --target tests --config Release
- name: Run tests (Release)
shell: cmd
run: |
cd ../boost-root/__build__
ctest --output-on-failure --no-tests=error -C Release

View File

@ -1,8 +1,9 @@
# Copyright 2018, 2019 Peter Dimov # Generated by `boostdep --cmake variant2`
# Copyright 2020, 2021 Peter Dimov
# Distributed under the Boost Software License, Version 1.0. # 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) cmake_minimum_required(VERSION 3.8...3.20)
project(boost_variant2 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX) project(boost_variant2 VERSION "${BOOST_SUPERPROJECT_VERSION}" LANGUAGES CXX)
@ -13,11 +14,23 @@ target_include_directories(boost_variant2 INTERFACE include)
target_link_libraries(boost_variant2 target_link_libraries(boost_variant2
INTERFACE INTERFACE
Boost::assert
Boost::config Boost::config
Boost::mp11 Boost::mp11
) )
if(BUILD_TESTING) if(CMAKE_VERSION VERSION_GREATER 3.18 AND CMAKE_GENERATOR MATCHES "Visual Studio")
file(GLOB_RECURSE boost_variant2_IDEFILES CONFIGURE_DEPENDS include/*.hpp)
source_group(TREE ${PROJECT_SOURCE_DIR}/include FILES ${boost_variant2_IDEFILES} PREFIX "Header Files")
list(APPEND boost_variant2_IDEFILES extra/boost_variant2.natvis)
target_sources(boost_variant2 PRIVATE ${boost_variant2_IDEFILES})
endif()
target_compile_features(boost_variant2 INTERFACE cxx_std_11)
if(BUILD_TESTING AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/test/CMakeLists.txt")
add_subdirectory(test) add_subdirectory(test)

View File

@ -1,21 +1,18 @@
# variant2 # Boost.Variant2
This repository contains a never-valueless, strong guarantee, C++11/14/17 This repository contains a never-valueless, strong guarantee, C++11/14/17
implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant). implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant).
See [the documentation](https://www.boost.org/libs/variant2) See [the documentation](https://www.boost.org/libs/variant2)
for more information. for more information.
The code requires [Boost.Mp11](https://github.com/boostorg/mp11) and The library is part of Boost, starting from release 1.71. It depends on
Boost.Config. Boost.Mp11, Boost.Config, and Boost.Assert.
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).
Supported compilers: Supported compilers:
* g++ 4.8 or later with `-std=c++11` or above * 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 * Visual Studio 2015 or later
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). [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. # 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) # (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
@ -21,14 +21,25 @@ environment:
TOOLSET: msvc-14.1 TOOLSET: msvc-14.1
ADDRMD: 32,64 ADDRMD: 32,64
CXXSTD: 14,17,latest CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: msvc-14.1
ADDRMD: 32,64
CXXSTD: 14,17,latest
CXXFLAGS: /permissive-
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
TOOLSET: clang-win TOOLSET: clang-win
ADDRMD: 64 ADDRMD: 64
CXXSTD: 14,17,latest CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019 - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
TOOLSET: msvc-14.2 TOOLSET: clang-win
ADDRMD: 32,64 ADDRMD: 64
CXXSTD: 14,17,latest CXXSTD: 14,17,latest
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
CMAKE: 1
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
CMAKE_SUBDIR: 1
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
CMAKE_INSTALL: 1
install: install:
- set BOOST_BRANCH=develop - set BOOST_BRANCH=develop
@ -47,4 +58,28 @@ build: off
test_script: test_script:
- if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD% - if not "%CXXSTD%" == "" set CXXSTD=cxxstd=%CXXSTD%
- if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD% - if not "%ADDRMD%" == "" set ADDRMD=address-model=%ADDRMD%
- b2 -j3 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% variant=debug,release - if not "%CXXFLAGS%" == "" set CXXFLAGS=cxxflags=%CXXFLAGS%
- if "%CMAKE%%CMAKE_SUBDIR%%CMAKE_INSTALL%" == "" b2 -j3 libs/variant2/test toolset=%TOOLSET% %CXXSTD% %ADDRMD% %CXXFLAGS% variant=debug,release embed-manifest-via=linker
- if not "%CMAKE%" == "" mkdir __build__ && cd __build__
- if not "%CMAKE%" == "" cmake -DBUILD_TESTING=ON -DBOOST_INCLUDE_LIBRARIES=variant2 -DBoost_VERBOSE=ON ..
- if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config Debug & ctest --output-on-failure --no-tests=error -j 3 -C Debug
- if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config Release & ctest --output-on-failure --no-tests=error -j 3 -C Release
- if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config MinSizeRel & ctest --output-on-failure --no-tests=error -j 3 -C MinSizeRel
- if not "%CMAKE%" == "" cmake --build . --target tests -j 3 --config RelWithDebInfo & ctest --output-on-failure --no-tests=error -j 3 -C RelWithDebInfo
- if not "%CMAKE_SUBDIR%" == "" cd libs/variant2/test/cmake_subdir_test && mkdir __build__ && cd __build__
- if not "%CMAKE_SUBDIR%" == "" cmake ..
- if not "%CMAKE_SUBDIR%" == "" cmake --build . --config Debug && cmake --build . --target check --config Debug
- if not "%CMAKE_SUBDIR%" == "" cmake --build . --config Release && cmake --build . --target check --config Release
- if not "%CMAKE_SUBDIR%" == "" cmake --build . --config MinSizeRel && cmake --build . --target check --config MinSizeRel
- if not "%CMAKE_SUBDIR%" == "" cmake --build . --config RelWithDebInfo && cmake --build . --target check --config RelWithDebInfo
- if not "%CMAKE_INSTALL%" == "" mkdir __build__ && cd __build__
- if not "%CMAKE_INSTALL%" == "" cmake -DBOOST_INCLUDE_LIBRARIES=variant2 -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
- if not "%CMAKE_INSTALL%" == "" cmake --build . --target install --config Debug
- if not "%CMAKE_INSTALL%" == "" cmake --build . --target install --config Release
- if not "%CMAKE_INSTALL%" == "" cd ../libs/variant2/test/cmake_install_test && mkdir __build__ && cd __build__
- if not "%CMAKE_INSTALL%" == "" cmake -DCMAKE_INSTALL_PREFIX=C:/cmake-prefix ..
- if not "%CMAKE_INSTALL%" == "" cmake --build . --config Debug && cmake --build . --target check --config Debug
- if not "%CMAKE_INSTALL%" == "" cmake --build . --config Release && cmake --build . --target check --config Release

View File

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

View File

@ -1,16 +1,32 @@
//// ////
Copyright 2019-2021 Peter Dimov Copyright 2019-2022 Peter Dimov
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
//// ////
[#changelog] [#changelog]
# Revision History # Revision History
:idprefix: changelog_ :idprefix: changelog_
## Changes in 1.83.0
* Added `uses_double_storage()`.
## Changes in 1.81.0
* Added support for `boost::json::value_from` and `boost::json::value_to`.
## 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 ## Changes in 1.76.0
* Improved generated code for the double buffered case. * Improved generated code for the double buffered case.

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...>`. `variant<int, float>` is provided as the member function `subset<U...>`.
(This operation can throw if the current state of the variant cannot be (This operation can throw if the current state of the variant cannot be
represented.) 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 * The {cpp}20 additions and changes to `std::variant` have not yet been
implemented. implemented.

View File

@ -1,10 +1,7 @@
//// ////
Copyright 2019 Peter Dimov Copyright 2019 Peter Dimov
Distributed under the Boost Software License, Version 1.0. Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
//// ////
[#implementation] [#implementation]
@ -13,13 +10,13 @@ http://www.boost.org/LICENSE_1_0.txt
## Dependencies ## 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 ## Supported Compilers
* GCC 4.8 or later with `-std=c++11` or above * 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 * Visual Studio 2015 or later
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]. 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. Distributed under the Boost Software License, Version 1.0.
https://www.boost.org/LICENSE_1_0.txt
See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt
//// ////
[#reference] [#reference]
@ -117,6 +114,21 @@ template<class U, class... T>
constexpr add_pointer_t<const U> constexpr add_pointer_t<const U>
get_if(const variant<T...>* v) noexcept; 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 // relational operators
template<class... T> template<class... T>
@ -132,11 +144,21 @@ template<class... T>
template<class... T> template<class... T>
constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w); 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 // visit
template<class R = /*unspecified*/, class F, class... V> template<class R = /*unspecified*/, class F, class... V>
constexpr /*see below*/ visit(F&& f, V&&... 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 // monostate
struct 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; }
constexpr bool operator>=(monostate, monostate) noexcept { return true; } constexpr bool operator>=(monostate, monostate) noexcept { return true; }
// swap // stream insertion (extension)
template<class... T> template<class Ch, class Tr, class... T>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ ); 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 // bad_variant_access
@ -223,6 +250,8 @@ public:
constexpr bool valueless_by_exception() const noexcept; constexpr bool valueless_by_exception() const noexcept;
constexpr size_t index() const noexcept; constexpr size_t index() const noexcept;
static constexpr bool uses_double_storage() noexcept;
// swap // swap
void swap( variant& r ) noexcept( /*see below*/ ); void swap( variant& r ) noexcept( /*see below*/ );
@ -543,6 +572,18 @@ constexpr size_t index() const noexcept;
Returns: :: Returns: ::
The zero-based index of the active alternative. The zero-based index of the active alternative.
```
static constexpr bool uses_double_storage() noexcept;
```
[none]
* {blank}
+
Returns: ::
`true` if the variant uses double storage to meet the never valueless
guarantee because one of the alternatives is not nothrow move constructible,
and `false` otherwise.
#### Swap #### Swap
``` ```
@ -775,6 +816,34 @@ Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the
Effects: :: Equivalent to: `return get_if<I>(v);` with `I` being Effects: :: Equivalent to: `return get_if<I>(v);` with `I` being
the zero-based index of `U` in `T...`. 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 ### Relational Operators
``` ```
@ -835,6 +904,18 @@ template<class... T>
Returns: :: Returns: ::
`w \<= v`. `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 ### visit
``` ```
@ -851,17 +932,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 of `F` to the variant alternatives must have the same return type for
this deduction to succeed. this deduction to succeed.
### swap ### visit_by_index (extension)
``` ```
template<class... T> template<class R = /*unspecified*/, class V, class... F>
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ ); 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] [none]
* {blank} * {blank}
+ +
Effects: :: Effects: ::
Equivalent to `v.swap(w)`. `os << "monostate"`.
Returns: ::
`os`.
### bad_variant_access ### bad_variant_access
@ -878,3 +992,7 @@ public:
} }
}; };
``` ```
## <boost/variant2.hpp>
This convenience header includes `<boost/variant2/variant.hpp>`.

178
extra/boost_variant2.natvis Normal file
View File

@ -0,0 +1,178 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="boost::variant2::detail::variant_base_impl&lt;*,1,*&gt;">
<Intrinsic Name="index" Expression="(int)ix_ - 1"/>
<DisplayString Condition="index() == 0" Optional="true">{{ index=0, value={*($T2*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 1" Optional="true">{{ index=1, value={*($T3*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 2" Optional="true">{{ index=2, value={*($T4*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 3" Optional="true">{{ index=3, value={*($T5*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 4" Optional="true">{{ index=4, value={*($T6*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 5" Optional="true">{{ index=5, value={*($T7*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 6" Optional="true">{{ index=6, value={*($T8*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 7" Optional="true">{{ index=7, value={*($T9*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 8" Optional="true">{{ index=8, value={*($T10*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 9" Optional="true">{{ index=9, value={*($T11*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 10" Optional="true">{{ index=10, value={*($T12*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 11" Optional="true">{{ index=11, value={*($T13*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 12" Optional="true">{{ index=12, value={*($T14*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 13" Optional="true">{{ index=13, value={*($T15*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 14" Optional="true">{{ index=14, value={*($T16*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 15" Optional="true">{{ index=15, value={*($T17*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 16" Optional="true">{{ index=16, value={*($T18*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 17" Optional="true">{{ index=17, value={*($T19*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 18" Optional="true">{{ index=18, value={*($T20*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 19" Optional="true">{{ index=19, value={*($T21*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 20" Optional="true">{{ index=10, value={*($T22*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 21" Optional="true">{{ index=21, value={*($T23*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 22" Optional="true">{{ index=22, value={*($T24*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 23" Optional="true">{{ index=23, value={*($T25*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 24" Optional="true">{{ index=24, value={*($T26*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 25" Optional="true">{{ index=25, value={*($T27*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 26" Optional="true">{{ index=26, value={*($T28*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 27" Optional="true">{{ index=27, value={*($T29*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 28" Optional="true">{{ index=28, value={*($T30*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 29" Optional="true">{{ index=29, value={*($T31*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 30" Optional="true">{{ index=30, value={*($T32*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 31" Optional="true">{{ index=31, value={*($T33*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 32" Optional="true">{{ index=32, value={*($T34*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 33" Optional="true">{{ index=33, value={*($T35*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 34" Optional="true">{{ index=34, value={*($T36*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 35" Optional="true">{{ index=35, value={*($T37*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 36" Optional="true">{{ index=36, value={*($T38*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 37" Optional="true">{{ index=37, value={*($T39*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 38" Optional="true">{{ index=38, value={*($T40*)&amp;st_} }}</DisplayString>
<DisplayString Condition="index() == 39" Optional="true">{{ index=39, value={*($T41*)&amp;st_} }}</DisplayString>
<Expand>
<Item Name="index">index()</Item>
<Item Name="[value]" Condition="index() == 0" Optional="true">*($T2*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 1" Optional="true">*($T3*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 2" Optional="true">*($T4*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 3" Optional="true">*($T5*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 4" Optional="true">*($T6*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 5" Optional="true">*($T7*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 6" Optional="true">*($T8*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 7" Optional="true">*($T9*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 8" Optional="true">*($T10*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 9" Optional="true">*($T11*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 10" Optional="true">*($T12*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 11" Optional="true">*($T13*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 12" Optional="true">*($T14*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 13" Optional="true">*($T15*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 14" Optional="true">*($T16*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 15" Optional="true">*($T17*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 16" Optional="true">*($T18*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 17" Optional="true">*($T19*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 18" Optional="true">*($T20*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 19" Optional="true">*($T21*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 20" Optional="true">*($T22*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 21" Optional="true">*($T23*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 22" Optional="true">*($T24*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 23" Optional="true">*($T25*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 24" Optional="true">*($T26*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 25" Optional="true">*($T27*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 26" Optional="true">*($T28*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 27" Optional="true">*($T29*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 28" Optional="true">*($T30*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 29" Optional="true">*($T31*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 30" Optional="true">*($T32*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 31" Optional="true">*($T33*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 32" Optional="true">*($T34*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 33" Optional="true">*($T35*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 34" Optional="true">*($T36*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 35" Optional="true">*($T37*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 36" Optional="true">*($T38*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 37" Optional="true">*($T39*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 38" Optional="true">*($T40*)&amp;st_</Item>
<Item Name="[value]" Condition="index() == 39" Optional="true">*($T41*)&amp;st_</Item>
</Expand>
</Type>
<Type Name="boost::variant2::detail::variant_base_impl&lt;*,0,*&gt;">
<Intrinsic Name="index" Expression="(int)((ix_-2)/2)"/>
<DisplayString Condition="index() == 0" Optional="true">{{ index=0, value={*($T2*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 1" Optional="true">{{ index=1, value={*($T3*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 2" Optional="true">{{ index=2, value={*($T4*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 3" Optional="true">{{ index=3, value={*($T5*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 4" Optional="true">{{ index=4, value={*($T6*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 5" Optional="true">{{ index=5, value={*($T7*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 6" Optional="true">{{ index=6, value={*($T8*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 7" Optional="true">{{ index=7, value={*($T9*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 8" Optional="true">{{ index=8, value={*($T10*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 9" Optional="true">{{ index=9, value={*($T11*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 10" Optional="true">{{ index=10, value={*($T12*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 11" Optional="true">{{ index=11, value={*($T13*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 12" Optional="true">{{ index=12, value={*($T14*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 13" Optional="true">{{ index=13, value={*($T15*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 14" Optional="true">{{ index=14, value={*($T16*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 15" Optional="true">{{ index=15, value={*($T17*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 16" Optional="true">{{ index=16, value={*($T18*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 17" Optional="true">{{ index=17, value={*($T19*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 18" Optional="true">{{ index=18, value={*($T20*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 19" Optional="true">{{ index=19, value={*($T21*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 20" Optional="true">{{ index=20, value={*($T22*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 21" Optional="true">{{ index=21, value={*($T23*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 22" Optional="true">{{ index=22, value={*($T24*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 23" Optional="true">{{ index=23, value={*($T25*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 24" Optional="true">{{ index=24, value={*($T26*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 25" Optional="true">{{ index=25, value={*($T27*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 26" Optional="true">{{ index=26, value={*($T28*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 27" Optional="true">{{ index=27, value={*($T29*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 28" Optional="true">{{ index=28, value={*($T30*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 29" Optional="true">{{ index=29, value={*($T31*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 30" Optional="true">{{ index=30, value={*($T32*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 31" Optional="true">{{ index=31, value={*($T33*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 32" Optional="true">{{ index=32, value={*($T34*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 33" Optional="true">{{ index=33, value={*($T35*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 34" Optional="true">{{ index=34, value={*($T36*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 35" Optional="true">{{ index=35, value={*($T37*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 36" Optional="true">{{ index=36, value={*($T38*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 37" Optional="true">{{ index=37, value={*($T39*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 38" Optional="true">{{ index=38, value={*($T40*)&amp;st_[ix_%2]} }}</DisplayString>
<DisplayString Condition="index() == 39" Optional="true">{{ index=39, value={*($T41*)&amp;st_[ix_%2]} }}</DisplayString>
<Expand>
<Item Name="index">index()</Item>
<Item Name="[value]" Condition="index() == 0" Optional="true">*($T2*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 1" Optional="true">*($T3*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 2" Optional="true">*($T4*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 3" Optional="true">*($T5*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 4" Optional="true">*($T6*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 5" Optional="true">*($T7*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 6" Optional="true">*($T8*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 7" Optional="true">*($T9*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 8" Optional="true">*($T10*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 9" Optional="true">*($T11*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 10" Optional="true">*($T12*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 11" Optional="true">*($T13*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 12" Optional="true">*($T14*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 13" Optional="true">*($T15*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 14" Optional="true">*($T16*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 15" Optional="true">*($T17*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 16" Optional="true">*($T18*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 17" Optional="true">*($T19*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 18" Optional="true">*($T20*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 19" Optional="true">*($T21*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 20" Optional="true">*($T22*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 21" Optional="true">*($T23*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 22" Optional="true">*($T24*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 23" Optional="true">*($T25*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 24" Optional="true">*($T26*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 25" Optional="true">*($T27*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 26" Optional="true">*($T28*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 27" Optional="true">*($T29*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 28" Optional="true">*($T30*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 29" Optional="true">*($T31*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 30" Optional="true">*($T32*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 31" Optional="true">*($T33*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 32" Optional="true">*($T34*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 33" Optional="true">*($T35*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 34" Optional="true">*($T36*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 35" Optional="true">*($T37*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 36" Optional="true">*($T38*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 37" Optional="true">*($T39*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 38" Optional="true">*($T40*)&amp;st_[ix_%2]</Item>
<Item Name="[value]" Condition="index() == 39" Optional="true">*($T41*)&amp;st_[ix_%2]</Item>
</Expand>
</Type>
</AutoVisualizer>

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,20 +13,19 @@
# pragma warning( disable: 4521 4522 ) // multiple copy operators # pragma warning( disable: 4521 4522 ) // multiple copy operators
#endif #endif
#ifndef BOOST_MP11_HPP_INCLUDED
#include <boost/mp11.hpp> #include <boost/mp11.hpp>
#endif #include <boost/assert.hpp>
#include <boost/assert/source_location.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/config/workaround.hpp>
#include <boost/cstdint.hpp>
#include <cstddef> #include <cstddef>
#include <type_traits> #include <type_traits>
#include <exception> #include <exception>
#include <cassert>
#include <initializer_list>
#include <utility> #include <utility>
#include <functional> // std::hash #include <typeindex> // std::hash
#include <iosfwd>
#include <cstdint> #include <cstdint>
#include <cerrno>
// //
@ -367,37 +366,50 @@ template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T
#endif #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) 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" ); 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>() ); 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) 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" ); 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>() ) ); 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) 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" ); 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>() ); 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) 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" ); 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>() ) ); return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
} }
} // namespace detail
// get (type) // get (type)
template<class U, class... T> constexpr U& get(variant<T...>& v) template<class U, class... T> constexpr U& get(variant<T...>& v)
@ -673,7 +685,20 @@ template<class T1, class... T> union variant_storage_impl<mp11::mp_true, T1, T..
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace_impl( mp11::mp_true, mp11::mp_size_t<I>, 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 )
{ {
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
# pragma GCC diagnostic push
// False positive in at least GCC 7 and GCC 10 ASAN triggered by monostate (via result<void>)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#if __GNUC__ >= 12
// False positive in at least GCC 12 and GCC 13 ASAN and -Og triggered by monostate (via result<void>)
# pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#endif
*this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... ); *this = variant_storage_impl( mp11::mp_size_t<I>(), std::forward<A>(a)... );
#if defined(BOOST_GCC) && (__GNUC__ >= 7)
# pragma GCC diagnostic pop
#endif
} }
template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a ) template<std::size_t I, class... A> BOOST_CXX14_CONSTEXPR void emplace( mp11::mp_size_t<I>, A&&... a )
@ -830,14 +855,14 @@ struct none {};
// trivially destructible, single buffered // trivially destructible, single buffered
template<class... T> struct variant_base_impl<true, true, T...> template<class... T> struct variant_base_impl<true, true, T...>
{ {
unsigned ix_;
variant_storage<none, T...> st_; variant_storage<none, T...> st_;
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st_( 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 ), st_( 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 )
{ {
} }
@ -857,7 +882,7 @@ template<class... T> struct variant_base_impl<true, true, T...>
{ {
size_t const J = I+1; size_t const J = I+1;
assert( ix_ == J ); BOOST_ASSERT( ix_ == J );
return st_.get( mp11::mp_size_t<J>() ); return st_.get( mp11::mp_size_t<J>() );
} }
@ -865,7 +890,8 @@ template<class... T> struct variant_base_impl<true, true, T...>
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept 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; // size_t const J = I+1;
// assert( ix_ == I+1 );
BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
return st_.get( mp11::mp_size_t<I+1>() ); return st_.get( mp11::mp_size_t<I+1>() );
} }
@ -895,19 +921,24 @@ template<class... T> struct variant_base_impl<true, true, T...>
this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... ); this->emplace_impl<J, U>( std::is_nothrow_constructible<U, A&&...>(), std::forward<A>(a)... );
} }
static constexpr bool uses_double_storage() noexcept
{
return false;
}
}; };
// trivially destructible, double buffered // trivially destructible, double buffered
template<class... T> struct variant_base_impl<true, false, T...> template<class... T> struct variant_base_impl<true, false, T...>
{ {
unsigned ix_;
variant_storage<none, T...> st_[ 2 ]; variant_storage<none, T...> st_[ 2 ];
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st_{ { mp11::mp_size_t<0>() }, { 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 ) * 2 ), st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { 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 )
{ {
} }
@ -925,7 +956,7 @@ template<class... T> struct variant_base_impl<true, false, T...>
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{ {
assert( index() == I ); BOOST_ASSERT( index() == I );
size_t const J = I+1; size_t const J = I+1;
@ -935,7 +966,8 @@ template<class... T> struct variant_base_impl<true, false, T...>
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{ {
// assert( index() == I ); BOOST_VARIANT2_CX14_ASSERT( index() == I )
// size_t const J = I+1; // size_t const J = I+1;
// constexpr mp_size_t<J> j{}; // constexpr mp_size_t<J> j{};
@ -952,19 +984,24 @@ template<class... T> struct variant_base_impl<true, false, T...>
ix_ = J * 2 + i2; ix_ = J * 2 + i2;
} }
static constexpr bool uses_double_storage() noexcept
{
return true;
}
}; };
// not trivially destructible, single buffered // not trivially destructible, single buffered
template<class... T> struct variant_base_impl<false, true, T...> template<class... T> struct variant_base_impl<false, true, T...>
{ {
unsigned ix_;
variant_storage<none, T...> st_; variant_storage<none, T...> st_;
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st_( 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 ), st_( 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 )
{ {
} }
@ -1013,7 +1050,7 @@ template<class... T> struct variant_base_impl<false, true, T...>
{ {
size_t const J = I+1; size_t const J = I+1;
assert( ix_ == J ); BOOST_ASSERT( ix_ == J );
return st_.get( mp11::mp_size_t<J>() ); return st_.get( mp11::mp_size_t<J>() );
} }
@ -1021,7 +1058,8 @@ template<class... T> struct variant_base_impl<false, true, T...>
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept 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; // size_t const J = I+1;
// assert( ix_ == J );
BOOST_VARIANT2_CX14_ASSERT( ix_ == I+1 )
return st_.get( mp11::mp_size_t<I+1>() ); return st_.get( mp11::mp_size_t<I+1>() );
} }
@ -1041,24 +1079,28 @@ template<class... T> struct variant_base_impl<false, true, T...>
st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) ); st_.emplace( mp11::mp_size_t<J>(), std::move(tmp) );
ix_ = J; ix_ = J;
} }
static constexpr bool uses_double_storage() noexcept
{
return false;
}
}; };
// not trivially destructible, double buffered // not trivially destructible, double buffered
template<class... T> struct variant_base_impl<false, false, T...> template<class... T> struct variant_base_impl<false, false, T...>
{ {
unsigned ix_;
#if defined(__GNUC__) && __GNUC__ < 11 && !defined(__clang__) && !defined(__INTEL_COMPILER) #if defined(__GNUC__) && __GNUC__ < 11 && !defined(__clang__) && !defined(__INTEL_COMPILER)
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 :-( // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63707 :-(
variant_storage<none, T...> st1_, st2_; variant_storage<none, T...> st1_, st2_;
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st1_( mp11::mp_size_t<0>() ), st2_( mp11::mp_size_t<0>() ) 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 ) * 2 ), 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 )
{ {
} }
@ -1075,12 +1117,13 @@ template<class... T> struct variant_base_impl<false, false, T...>
#else #else
variant_storage<none, T...> st_[ 2 ]; variant_storage<none, T...> st_[ 2 ];
unsigned ix_;
constexpr variant_base_impl(): ix_( 0 ), st_{ { mp11::mp_size_t<0>() }, { 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 ) * 2 ), st_{ { mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... }, { 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 )
{ {
} }
@ -1137,7 +1180,7 @@ template<class... T> struct variant_base_impl<false, false, T...>
template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept template<std::size_t I> BOOST_CXX14_CONSTEXPR mp11::mp_at_c<variant<T...>, I>& _get_impl( mp11::mp_size_t<I> ) noexcept
{ {
assert( index() == I ); BOOST_ASSERT( index() == I );
size_t const J = I+1; size_t const J = I+1;
@ -1147,7 +1190,8 @@ template<class... T> struct variant_base_impl<false, false, T...>
template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept template<std::size_t I> constexpr mp11::mp_at_c<variant<T...>, I> const& _get_impl( mp11::mp_size_t<I> ) const noexcept
{ {
// assert( index() == I ); BOOST_VARIANT2_CX14_ASSERT( index() == I )
// size_t const J = I+1; // size_t const J = I+1;
// constexpr mp_size_t<J> j{}; // constexpr mp_size_t<J> j{};
@ -1165,6 +1209,11 @@ template<class... T> struct variant_base_impl<false, false, T...>
ix_ = J * 2 + i2; ix_ = J * 2 + i2;
} }
static constexpr bool uses_double_storage() noexcept
{
return true;
}
}; };
} // namespace detail } // namespace detail
@ -1585,7 +1634,17 @@ public:
template<class U, template<class U,
class Ud = typename std::decay<U>::type, class Ud = typename std::decay<U>::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 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,
#if BOOST_WORKAROUND(BOOST_MSVC, < 1950)
class V = mp11::mp_apply_q< mp11::mp_bind_front<detail::resolve_overload_type, U&&>, variant >,
#else
class V = detail::resolve_overload_type<U&&, T...>, class V = detail::resolve_overload_type<U&&, T...>,
#endif
class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type class E2 = typename std::enable_if<std::is_constructible<V, U&&>::value>::type
> >
constexpr variant( U&& u ) constexpr variant( U&& u )
@ -1675,6 +1734,8 @@ public:
using variant_base::index; using variant_base::index;
using variant_base::uses_double_storage;
// swap // swap
private: private:
@ -2176,7 +2237,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 ){ 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)... ); return visit<R>( f2, std::forward<V2>(v2), std::forward<V>(v)... );
}); });
@ -2193,6 +2254,75 @@ void swap( variant<T...> & v, variant<T...> & w )
v.swap( 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 // hashing support
namespace detail namespace detail
@ -2200,8 +2330,8 @@ namespace detail
inline std::size_t hash_value_impl_( mp11::mp_true, std::size_t index, std::size_t value ) 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; unsigned long long hv = 0xCBF29CE484222325ull;
boost::ulong_long_type const prime = ( boost::ulong_long_type( 0x00000100 ) << 32 ) + 0x000001B3; unsigned long long const prime = 0x100000001B3ull;
hv ^= index; hv ^= index;
hv *= prime; hv *= prime;
@ -2307,6 +2437,111 @@ template<> struct hash< ::boost::variant2::monostate >
} // namespace std } // namespace std
// JSON support
namespace boost
{
namespace json
{
class value;
struct value_from_tag;
template<class T>
void value_from( T&& t, value& jv );
template<class T>
struct try_value_to_tag;
template<class T1, class T2>
struct result_for;
template<class T>
typename result_for<T, value>::type
try_value_to( value const & jv );
template<class T>
typename result_for<T, value>::type
result_from_errno( int e, boost::source_location const* loc ) noexcept;
template<class T> struct is_null_like;
template<> struct is_null_like<variant2::monostate>: std::true_type {};
} // namespace json
namespace variant2
{
namespace detail
{
struct tag_invoke_L1
{
boost::json::value& v;
#if defined(BOOST_MSVC) && BOOST_MSVC / 10 == 191
// msvc-14.1 with /permissive- needs this
explicit tag_invoke_L1( boost::json::value& v_ ): v( v_ ) {}
#endif
template<class T> void operator()( T const& t ) const
{
boost::json::value_from( t, v );
}
};
} // namespace detail
template<class... T>
void tag_invoke( boost::json::value_from_tag const&, boost::json::value& v, variant<T...> const & w )
{
visit( detail::tag_invoke_L1{ v }, w );
}
namespace detail
{
template<class V> struct tag_invoke_L2
{
boost::json::value const& v;
typename boost::json::result_for<V, boost::json::value>::type& r;
template<class I> void operator()( I /*i*/ ) const
{
if( !r )
{
using Ti = mp11::mp_at_c<V, I::value>;
auto r2 = boost::json::try_value_to<Ti>( v );
if( r2 )
{
r.emplace( in_place_index_t<I::value>{}, std::move( *r2 ) );
}
}
}
};
} // namespace detail
template<class... T>
typename boost::json::result_for<variant<T...>, boost::json::value>::type
tag_invoke( boost::json::try_value_to_tag<variant<T...>> const&, boost::json::value const& v )
{
static constexpr boost::source_location loc = BOOST_CURRENT_LOCATION;
auto r = boost::json::result_from_errno< variant<T...> >( EINVAL, &loc );
mp11::mp_for_each<mp11::mp_iota_c<sizeof...(T)>>( detail::tag_invoke_L2< variant<T...> >{ v, r } );
return r;
}
} // namespace variant2
} // namespace boost
#undef BOOST_VARIANT2_CX14_ASSERT
#if defined(_MSC_VER) && _MSC_VER < 1910 #if defined(_MSC_VER) && _MSC_VER < 1910
# pragma warning( pop ) # pragma warning( pop )
#endif #endif

View File

@ -16,8 +16,6 @@ project
: requirements : requirements
[ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_constexpr ]
<toolset>msvc:<warnings-as-errors>on <toolset>msvc:<warnings-as-errors>on
<toolset>gcc:<warnings-as-errors>on <toolset>gcc:<warnings-as-errors>on
<toolset>clang:<warnings-as-errors>on <toolset>clang:<warnings-as-errors>on
@ -121,3 +119,17 @@ run variant_visit_r.cpp : : :
; ;
compile variant_derived_construct.cpp ; compile variant_derived_construct.cpp ;
run variant_visit_by_index.cpp ;
run variant_ostream_insert.cpp ;
run is_output_streamable.cpp ;
local JSON = <library>/boost//json/<warnings>off "<toolset>msvc-14.0:<build>no" "<toolset>msvc-14.2:<cxxflags>-wd5104" "<undefined-sanitizer>norecover:<link>static" ;
run variant_json_value_from.cpp : : : $(JSON) ;
run variant_json_value_to.cpp : : : $(JSON) ;
compile variant_uses_double_storage.cpp ;
run variant_derived_construct2.cpp ;

View File

@ -7,6 +7,8 @@ cmake_minimum_required(VERSION 3.5...3.16)
project(cmake_subdir_test LANGUAGES CXX) project(cmake_subdir_test LANGUAGES CXX)
add_subdirectory(../.. boostorg/variant2) add_subdirectory(../.. boostorg/variant2)
add_subdirectory(../../../assert boostorg/assert)
add_subdirectory(../../../config boostorg/config) add_subdirectory(../../../config boostorg/config)
add_subdirectory(../../../mp11 boostorg/mp11) 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. // Copyright 2019 Peter Dimov.
//
// Distributed under the Boost Software License, Version 1.0. // 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; using namespace boost::variant2;

View File

@ -0,0 +1,60 @@
// Copyright 2024 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>
struct expr: boost::variant2::variant<bool, int, double>
{
using variant::variant;
};
int main()
{
using boost::variant2::get;
{
expr v{ true };
BOOST_TEST_EQ( v.index(), 0 );
BOOST_TEST_EQ( get<0>(v), true );
}
{
expr v{ 2 };
BOOST_TEST_EQ( v.index(), 1 );
BOOST_TEST_EQ( get<1>(v), 2 );
}
{
expr v{ 3.0 };
BOOST_TEST_EQ( v.index(), 2 );
BOOST_TEST_EQ( get<2>(v), 3.0 );
}
{
expr v( true );
BOOST_TEST_EQ( v.index(), 0 );
BOOST_TEST_EQ( get<0>(v), true );
}
{
expr v( 2 );
BOOST_TEST_EQ( v.index(), 1 );
BOOST_TEST_EQ( get<1>(v), 2 );
}
{
expr v( 3.0 );
BOOST_TEST_EQ( v.index(), 2 );
BOOST_TEST_EQ( get<2>(v), 3.0 );
}
return boost::report_errors();
}

View File

@ -288,5 +288,39 @@ int main()
BOOST_TEST_EQ( Z1::instances, 0 ); BOOST_TEST_EQ( Z1::instances, 0 );
BOOST_TEST_EQ( Z2::instances, 0 ); BOOST_TEST_EQ( Z2::instances, 0 );
{
variant<monostate, monostate> v;
BOOST_TEST_EQ( v.index(), 0 );
v.emplace<0>();
BOOST_TEST_EQ( v.index(), 0 );
v.emplace<1>();
BOOST_TEST_EQ( v.index(), 1 );
v.emplace<1>();
BOOST_TEST_EQ( v.index(), 1 );
v.emplace<0>();
BOOST_TEST_EQ( v.index(), 0 );
}
{
variant<monostate, int> v;
BOOST_TEST_EQ( v.index(), 0 );
v.emplace<0>();
BOOST_TEST_EQ( v.index(), 0 );
v.emplace<1>();
BOOST_TEST_EQ( v.index(), 1 );
v.emplace<1>();
BOOST_TEST_EQ( v.index(), 1 );
v.emplace<0>();
BOOST_TEST_EQ( v.index(), 0 );
}
return boost::report_errors(); return boost::report_errors();
} }

View File

@ -58,7 +58,7 @@ int main()
{ {
constexpr variant<int, float> v( 3.14f ); constexpr variant<int, float> v( 3.14f );
STATIC_ASSERT( get<1>(v) == 3.14f ); STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD
STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); STATIC_ASSERT_IF( get_if<0>(&v) == nullptr );
STATIC_ASSERT_IF( get_if<1>(&v) == &get<1>(v) ); STATIC_ASSERT_IF( get_if<1>(&v) == &get<1>(v) );
@ -87,7 +87,7 @@ int main()
{ {
constexpr variant<int, int, float> v( 3.14f ); constexpr variant<int, int, float> v( 3.14f );
STATIC_ASSERT( get<2>(v) == 3.14f ); STATIC_ASSERT( get<2>(v) == (float)3.14f );
STATIC_ASSERT_IF( get_if<0>(&v) == nullptr ); STATIC_ASSERT_IF( get_if<0>(&v) == nullptr );
STATIC_ASSERT_IF( get_if<1>(&v) == nullptr ); STATIC_ASSERT_IF( get_if<1>(&v) == nullptr );

View File

@ -58,7 +58,7 @@ int main()
{ {
constexpr variant<int, float> v( 3.14f ); constexpr variant<int, float> v( 3.14f );
STATIC_ASSERT( get<float>(v) == 3.14f ); STATIC_ASSERT( get<float>(v) == (float)3.14f ); // see FLT_EVAL_METHOD
STATIC_ASSERT_IF( get_if<int>(&v) == nullptr ); STATIC_ASSERT_IF( get_if<int>(&v) == nullptr );
STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) ); STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) );
@ -83,7 +83,7 @@ int main()
{ {
constexpr variant<int, int, float> v( 3.14f ); constexpr variant<int, int, float> v( 3.14f );
STATIC_ASSERT( get<float>(v) == 3.14f ); STATIC_ASSERT( get<float>(v) == (float)3.14f );
STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) ); STATIC_ASSERT_IF( get_if<float>(&v) == &get<float>(v) );
} }

View File

@ -68,7 +68,7 @@ int main()
constexpr variant<int, float> v( in_place_index_t<1>{}, 3.14f ); constexpr variant<int, float> v( in_place_index_t<1>{}, 3.14f );
STATIC_ASSERT( v.index() == 1 ); STATIC_ASSERT( v.index() == 1 );
STATIC_ASSERT( get<1>(v) == 3.14f ); STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD
} }
{ {
@ -89,14 +89,14 @@ int main()
constexpr variant<int, int, float, float, X, X> v( in_place_index_t<2>{}, 3.14f ); constexpr variant<int, int, float, float, X, X> v( in_place_index_t<2>{}, 3.14f );
STATIC_ASSERT( v.index() == 2 ); STATIC_ASSERT( v.index() == 2 );
STATIC_ASSERT( get<2>(v) == 3.14f ); STATIC_ASSERT( get<2>(v) == (float)3.14f );
} }
{ {
constexpr variant<int, int, float, float, X, X> v( in_place_index_t<3>{}, 3.14f ); constexpr variant<int, int, float, float, X, X> v( in_place_index_t<3>{}, 3.14f );
STATIC_ASSERT( v.index() == 3 ); STATIC_ASSERT( v.index() == 3 );
STATIC_ASSERT( get<3>(v) == 3.14f ); STATIC_ASSERT( get<3>(v) == (float)3.14f );
} }
{ {
@ -105,9 +105,9 @@ int main()
STATIC_ASSERT( v.index() == 4 ); STATIC_ASSERT( v.index() == 4 );
} }
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 110000) #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 #else

View File

@ -80,7 +80,7 @@ int main()
constexpr variant<int, float> v( in_place_type_t<float>{}, 3.14f ); constexpr variant<int, float> v( in_place_type_t<float>{}, 3.14f );
STATIC_ASSERT( v.index() == 1 ); STATIC_ASSERT( v.index() == 1 );
STATIC_ASSERT( get<1>(v) == 3.14f ); STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD
STATIC_ASSERT( holds_alternative<float>(v) ); STATIC_ASSERT( holds_alternative<float>(v) );
} }
@ -89,7 +89,7 @@ int main()
constexpr variant<int, int, float, X> v( in_place_type_t<float>{}, 3.14f ); constexpr variant<int, int, float, X> v( in_place_type_t<float>{}, 3.14f );
STATIC_ASSERT( v.index() == 2 ); STATIC_ASSERT( v.index() == 2 );
STATIC_ASSERT( get<2>(v) == 3.14f ); STATIC_ASSERT( get<2>(v) == (float)3.14f );
STATIC_ASSERT( holds_alternative<float>(v) ); STATIC_ASSERT( holds_alternative<float>(v) );
} }
@ -102,9 +102,9 @@ int main()
STATIC_ASSERT( holds_alternative<X>(v) ); STATIC_ASSERT( holds_alternative<X>(v) );
} }
#if BOOST_WORKAROUND(BOOST_GCC, >= 100000 && BOOST_GCC < 110000) #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 #else

View File

@ -0,0 +1,41 @@
// Copyright 2022 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/json/value_from.hpp>
#include <boost/json/serialize.hpp>
#include <boost/core/lightweight_test.hpp>
#include <string>
using namespace boost::variant2;
namespace json = boost::json;
int main()
{
{
monostate m;
json::value w = json::value_from( m );
BOOST_TEST_EQ( w, json::value( nullptr ) );
}
{
variant<monostate, int, std::string> v;
json::value w = json::value_from( v );
BOOST_TEST_EQ( w, json::value( nullptr ) );
}
{
variant<monostate, int, std::string> v( 17 );
json::value w = json::value_from( v );
BOOST_TEST_EQ( w, json::value( 17 ) );
}
{
variant<monostate, int, std::string> v( "test" );
json::value w = json::value_from( v );
BOOST_TEST_EQ( w, json::value( "test" ) );
}
return boost::report_errors();
}

View File

@ -0,0 +1,42 @@
// Copyright 2022 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/json/value_to.hpp>
#include <boost/json/serialize.hpp>
#include <boost/core/lightweight_test.hpp>
using namespace boost::variant2;
namespace json = boost::json;
int main()
{
{
json::value v;
auto r = json::try_value_to<monostate>( v );
BOOST_TEST( r.has_value() );
}
using V = variant<monostate, int, std::string>;
{
json::value v;
auto r = json::try_value_to<V>( v );
BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V() );
}
{
json::value v( 12 );
auto r = json::try_value_to<V>( v );
BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V(12) );
}
{
json::value v( "test" );
auto r = json::try_value_to<V>( v );
BOOST_TEST( r.has_value() ) && BOOST_TEST_EQ( *r, V("test") );
}
return boost::report_errors();
}

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,50 @@
// Copyright 2023 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 <type_traits>
using namespace boost::variant2;
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
struct X1
{
};
STATIC_ASSERT( std::is_nothrow_move_constructible<X1>::value );
STATIC_ASSERT( std::is_trivially_destructible<X1>::value );
struct X2
{
~X2() {}
};
STATIC_ASSERT( std::is_nothrow_move_constructible<X2>::value );
STATIC_ASSERT( !std::is_trivially_destructible<X2>::value );
struct X3
{
X3( X3&& ) {}
};
STATIC_ASSERT( !std::is_nothrow_move_constructible<X3>::value );
STATIC_ASSERT( std::is_trivially_destructible<X3>::value );
struct X4
{
~X4() {}
X4( X4&& ) {}
};
STATIC_ASSERT( !std::is_nothrow_move_constructible<X4>::value );
STATIC_ASSERT( !std::is_trivially_destructible<X4>::value );
//
STATIC_ASSERT( !variant<int, float>::uses_double_storage() );
STATIC_ASSERT( !variant<int, float, X1>::uses_double_storage() );
STATIC_ASSERT( !variant<int, float, X2>::uses_double_storage() );
STATIC_ASSERT( variant<int, float, X3>::uses_double_storage() );
STATIC_ASSERT( variant<int, float, X4>::uses_double_storage() );

View File

@ -82,7 +82,7 @@ int main()
STATIC_ASSERT( v.index() == 1 ); STATIC_ASSERT( v.index() == 1 );
STATIC_ASSERT( holds_alternative<float>(v) ); STATIC_ASSERT( holds_alternative<float>(v) );
STATIC_ASSERT( get<1>(v) == 3.14f ); STATIC_ASSERT( get<1>(v) == (float)3.14f ); // see FLT_EVAL_METHOD
} }
{ {
@ -97,7 +97,7 @@ int main()
STATIC_ASSERT( v.index() == 2 ); STATIC_ASSERT( v.index() == 2 );
STATIC_ASSERT( holds_alternative<float>(v) ); STATIC_ASSERT( holds_alternative<float>(v) );
STATIC_ASSERT( get<2>(v) == 3.14f ); STATIC_ASSERT( get<2>(v) == (float)3.14f );
} }
{ {

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. // Copyright 2017, 2020 Peter Dimov.
// Distributed under the Boost Software License, Version 1.0. // Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt // https://www.boost.org/LICENSE_1_0.txt
@ -15,7 +14,7 @@
struct X: boost::variant2::variant<int, float> 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 ) ) {}; template<class T> explicit X( T&& t ): variant( std::forward<T>( t ) ) {};

View File

@ -61,18 +61,18 @@ int main()
} }
{ {
variant<int, float> const v( 3.14f ); variant<int, float> const v( 3.125f );
BOOST_TEST_EQ( visit<int>( F1(), v ), 3 ); BOOST_TEST_EQ( visit<int>( F1(), v ), 3 );
BOOST_TEST_EQ( visit<float>( F1(), v ), 3.14f ); BOOST_TEST_EQ( visit<float>( F1(), v ), 3.125f );
} }
{ {
variant<int, float> v1( 1 ); variant<int, float> v1( 1 );
variant<int, float> const v2( 3.14f ); variant<int, float> const v2( 3.125f );
BOOST_TEST_EQ( visit<int>( F2(), v1, v2 ), 4 ); BOOST_TEST_EQ( visit<int>( F2(), v1, v2 ), 4 );
BOOST_TEST_EQ( visit<float>( F2(), v1, v2 ), 1 + 3.14f ); BOOST_TEST_EQ( visit<float>( F2(), v1, v2 ), 1 + 3.125f );
} }
{ {