mirror of
https://github.com/boostorg/variant2.git
synced 2025-12-23 07:12:33 +01:00
Compare commits
43 Commits
feature/c+
...
feature/co
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c3526b3bb | ||
|
|
204bcce9df | ||
|
|
e5e09c1c04 | ||
|
|
2f589c7814 | ||
|
|
fdfe9df167 | ||
|
|
30d974d0fc | ||
|
|
9d7a44761b | ||
|
|
2f376da1c2 | ||
|
|
f05837061a | ||
|
|
3d946ecb71 | ||
|
|
8756a07f9a | ||
|
|
48c8145b4d | ||
|
|
8bbd6f238a | ||
|
|
1b62998c96 | ||
|
|
8a7cc12716 | ||
|
|
b97a92c963 | ||
|
|
ea2e8d2cf6 | ||
|
|
2ea2ff915b | ||
|
|
d6d1cbd9fe | ||
|
|
f4d852e5ab | ||
|
|
89c58a9b83 | ||
|
|
831231a8b3 | ||
|
|
4c8b0d2dee | ||
|
|
a0b499bc3b | ||
|
|
c1287f9e95 | ||
|
|
34933c35bd | ||
|
|
d8cd270268 | ||
|
|
87a2e88edb | ||
|
|
cf3ea64b45 | ||
|
|
f67a6bd2ae | ||
|
|
f3e101a841 | ||
|
|
5911e80f4f | ||
|
|
24fae0f542 | ||
|
|
8f2ef7ddc1 | ||
|
|
58709c2922 | ||
|
|
16027c5447 | ||
|
|
3fb89b9f5a | ||
|
|
33f28c739f | ||
|
|
c1d2d991b4 | ||
|
|
7c7779621f | ||
|
|
f14228d996 | ||
|
|
3fb00763cb | ||
|
|
ebc8959049 |
19
.travis.yml
19
.travis.yml
@@ -1,4 +1,4 @@
|
||||
# Copyright 2016-2018 Peter Dimov
|
||||
# Copyright 2016-2019 Peter Dimov
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
|
||||
|
||||
@@ -70,7 +70,7 @@ matrix:
|
||||
|
||||
- os: linux
|
||||
compiler: g++-8
|
||||
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17
|
||||
env: TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -80,7 +80,7 @@ matrix:
|
||||
|
||||
- os: linux
|
||||
compiler: g++-8
|
||||
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17 UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
|
||||
env: UBSAN=1 TOOLSET=gcc COMPILER=g++-8 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1 LINKFLAGS=-fuse-ld=gold
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@@ -177,9 +177,20 @@ matrix:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-6.0
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-7
|
||||
env: TOOLSET=clang COMPILER=clang++-7 CXXSTD=11,14,17,2a
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- clang-7
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-trusty-7
|
||||
|
||||
- os: linux
|
||||
compiler: clang++-6.0
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=11,14,1z UBSAN_OPTIONS=print_stacktrace=1
|
||||
env: UBSAN=1 TOOLSET=clang COMPILER=clang++-6.0 CXXSTD=11,14,17,2a UBSAN_OPTIONS=print_stacktrace=1
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
|
||||
58
README.md
58
README.md
@@ -1,34 +1,64 @@
|
||||
# variant2
|
||||
|
||||
This repository contains a never-valueless C++14 implementation of [std::variant](http://en.cppreference.com/w/cpp/utility/variant) in [variant.hpp](include/boost/variant2/variant.hpp) and an implementation of `expected<T, E...>` in [expected.hpp](include/boost/variant2/expected.hpp) that is an extended version of `expected<T, E>` as proposed in [P0323R1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0323r1.pdf) and the subsequent [D0323R2](https://github.com/viboes/std-make/blob/master/doc/proposal/expected/d0323r2.md).
|
||||
This repository contains a never-valueless C++11/14/17 implementation of
|
||||
[std::variant](http://en.cppreference.com/w/cpp/utility/variant) in
|
||||
[variant.hpp](include/boost/variant2/variant.hpp) and an implementation of
|
||||
`expected<T, E...>` in [expected.hpp](include/boost/variant2/expected.hpp)
|
||||
that is an extended version of `expected<T, E>` as proposed in
|
||||
[P0323R1](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0323r1.pdf)
|
||||
and the subsequent
|
||||
[D0323R2](https://github.com/viboes/std-make/blob/master/doc/proposal/expected/d0323r2.md).
|
||||
|
||||
The code requires [mp11](https://github.com/pdimov/mp11) and Boost.Config. The repository is intended to be placed into the `libs/variant2` directory of a Boost clone or release, with mp11 in `libs/mp11`, but the headers will also work standalone if [mp11.hpp](https://github.com/pdimov/mp11/blob/master/include/boost/mp11.hpp) or [mp11_single.hpp](https://github.com/pdimov/mp11/blob/master/include/boost/mp11_single.hpp) is included beforehand.
|
||||
The code requires [Boost.Mp11](https://github.com/boostorg/mp11) and
|
||||
Boost.Config.
|
||||
|
||||
The repository is intended to be placed into the `libs/variant2` directory of
|
||||
a Boost clone or release, but the header `variant.hpp` will also work
|
||||
[standalone](https://godbolt.org/z/CTZztA).
|
||||
|
||||
Supported compilers:
|
||||
|
||||
* g++ 5 or later with -std=c++14 or -std=c++1z
|
||||
* clang++ 3.5 or later with -std=c++14 or -std=c++1z
|
||||
* Visual Studio 2017
|
||||
* g++ 4.8 or later with `-std=c++11` or above
|
||||
* clang++ 3.5 or later with `-std=c++11` or above
|
||||
* Visual Studio 2015, 2017
|
||||
|
||||
Tested on [Travis](https://travis-ci.org/pdimov/variant2/) and [Appveyor](https://ci.appveyor.com/project/pdimov/variant2/).
|
||||
Tested on [Travis](https://travis-ci.org/pdimov/variant2/) and
|
||||
[Appveyor](https://ci.appveyor.com/project/pdimov/variant2/).
|
||||
|
||||
## variant.hpp
|
||||
|
||||
The class `boost::variant2::variant<T...>` is an almost conforming implementation of `std::variant` with the following differences:
|
||||
The class `boost::variant2::variant<T...>` is an almost conforming
|
||||
implementation of `std::variant` with the following differences:
|
||||
|
||||
* A converting constructor from, e.g. `variant<int, float>` to `variant<float, double, int>` is provided as an extension;
|
||||
* The reverse operation, going from `variant<float, double, int>` to `variant<int, float>` is provided as the member function `subset<U...>`. (This operation can throw if the current state of the variant cannot be represented.)
|
||||
* A converting constructor from, e.g. `variant<int, float>` to
|
||||
`variant<float, double, int>` is provided as an extension;
|
||||
* The reverse operation, going from `variant<float, double, int>` to
|
||||
`variant<int, float>` is provided as the member function `subset<U...>`.
|
||||
(This operation can throw if the current state of the variant cannot be
|
||||
represented.)
|
||||
* `variant<T...>` is not trivial when all contained types are trivial.
|
||||
|
||||
To avoid going into a valueless-by-exception state, this implementation falls back to using double storage unless
|
||||
To avoid going into a valueless-by-exception state, this implementation falls
|
||||
back to using double storage unless
|
||||
|
||||
* all the contained types are nothrow move constructible, or
|
||||
* the first alternative is the type `valueless`.
|
||||
* one of the alternatives is the type `monostate`,
|
||||
* one of the alternatives has a nonthrowing default constructor, or
|
||||
* all the contained types are nothrow move constructible.
|
||||
|
||||
If the second bullet doesn't hold, but the first does, the variant uses single storage, but `emplace` constructs a temporary and moves it into place if the construction of the object can throw. In case this is undesirable, one can force `emplace` into always constructing in-place by adding `valueless` as a first alternative.
|
||||
If the first two bullets don't hold, but the third does, the variant uses
|
||||
single storage, but `emplace` constructs a temporary and moves it into place
|
||||
if the construction of the object can throw. In case this is undesirable, one
|
||||
can force `emplace` into always constructing in-place by adding `monostate` as
|
||||
one of the alternatives.
|
||||
|
||||
## expected.hpp
|
||||
|
||||
The class `boost::variant2::expected<T, E...>` represents the return type of an operation that may potentially fail. It contains either the expected result of type `T`, or a reason for the failure, of one of the error types in `E...`. Internally, this is stored as `variant<T, E...>`.
|
||||
The class `boost::variant2::expected<T, E...>` represents the return type of
|
||||
an operation that may potentially fail. It contains either the expected result
|
||||
of type `T`, or a reason for the failure, of one of the error types in `E...`.
|
||||
Internally, this is stored as `variant<T, E...>`.
|
||||
|
||||
See [its documentation](doc/expected.md) for more information.
|
||||
|
||||
Note that, while `variant` is production quality, `expected` is still a work
|
||||
in progress and has no test suite yet.
|
||||
|
||||
168
benchmark/benchmark1.cpp
Normal file
168
benchmark/benchmark1.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(ONLY_V2)
|
||||
# define NO_BV
|
||||
# define NO_SV
|
||||
#endif
|
||||
|
||||
#if defined(ONLY_BV)
|
||||
# define NO_V2
|
||||
# define NO_SV
|
||||
#endif
|
||||
|
||||
#if defined(ONLY_SV)
|
||||
# define NO_V2
|
||||
# define NO_BV
|
||||
#endif
|
||||
|
||||
#if !defined(NO_V2)
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(NO_BV)
|
||||
#include <boost/variant.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(NO_SV)
|
||||
#include <variant>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
template<class T> struct is_numeric: std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, class U> struct have_addition: std::integral_constant<bool, is_numeric<T>::value && is_numeric<U>::value>
|
||||
{
|
||||
};
|
||||
|
||||
template<class T, class U, class E = std::enable_if_t<have_addition<T, U>::value>> auto add( T const& t, U const& u )
|
||||
{
|
||||
return t + u;
|
||||
}
|
||||
|
||||
template<class T, class U, class E = std::enable_if_t<!have_addition<T, U>::value>> double add( T const& /*t*/, U const& /*u*/ )
|
||||
{
|
||||
throw std::logic_error( "Invalid addition" );
|
||||
}
|
||||
|
||||
inline double to_double( double const& v )
|
||||
{
|
||||
return v;
|
||||
}
|
||||
|
||||
#if !defined(NO_V2)
|
||||
|
||||
template<class... T> boost::variant2::variant<T...> operator+( boost::variant2::variant<T...> const& v1, boost::variant2::variant<T...> const& v2 )
|
||||
{
|
||||
return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant<T...> { return add( x1, x2 ); }, v1, v2 );
|
||||
}
|
||||
|
||||
template<class... T> double to_double( boost::variant2::variant<T...> const& v )
|
||||
{
|
||||
return boost::variant2::get<double>( v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(NO_BV)
|
||||
|
||||
template<class... T> boost::variant<T...> operator+( boost::variant<T...> const& v1, boost::variant<T...> const& v2 )
|
||||
{
|
||||
return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant<T...> { return add( x1, x2 ); }, v1, v2 );
|
||||
}
|
||||
|
||||
template<class... T> double to_double( boost::variant<T...> const& v )
|
||||
{
|
||||
return boost::get<double>( v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(NO_SV)
|
||||
|
||||
template<class... T> std::variant<T...> operator+( std::variant<T...> const& v1, std::variant<T...> const& v2 )
|
||||
{
|
||||
return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant<T...> { return add( x1, x2 ); }, v1, v2 );
|
||||
}
|
||||
|
||||
template<class... T> double to_double( std::variant<T...> const& v )
|
||||
{
|
||||
return std::get<double>( v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class V> void test_( long long N )
|
||||
{
|
||||
std::vector<V> w;
|
||||
// lack of reserve is deliberate
|
||||
|
||||
auto tp1 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for( long long i = 0; i < N; ++i )
|
||||
{
|
||||
V v;
|
||||
|
||||
if( i % 7 == 0 )
|
||||
{
|
||||
v = i / 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = i / 7.0;
|
||||
}
|
||||
|
||||
w.push_back( v );
|
||||
}
|
||||
|
||||
V s = 0.0;
|
||||
|
||||
for( long long i = 0; i < N; ++i )
|
||||
{
|
||||
s = s + w[ i ];
|
||||
}
|
||||
|
||||
auto tp2 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n";
|
||||
}
|
||||
|
||||
template<class... T> void test( long long N )
|
||||
{
|
||||
std::cout << "N=" << N << ":\n";
|
||||
|
||||
std::cout << " double: "; test_<double>( N );
|
||||
#if !defined(NO_V2)
|
||||
std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N );
|
||||
#endif
|
||||
#if !defined(NO_BV)
|
||||
std::cout << "boost::variant: "; test_<boost::variant<T...>>( N );
|
||||
#endif
|
||||
#if !defined(NO_SV)
|
||||
std::cout << " std::variant: "; test_<std::variant<T...>>( N );
|
||||
#endif
|
||||
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
long long const N = 100'000'000LL;
|
||||
|
||||
test<long long, double>( N );
|
||||
test<std::nullptr_t, long long, double, std::string, std::vector<std::string>, std::map<std::string, std::string>>( N );
|
||||
}
|
||||
267
benchmark/benchmark1.md
Normal file
267
benchmark/benchmark1.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# benchmark1.cpp results
|
||||
|
||||
## VS 2017 15.9.7 64 bit (cl.exe 19.16, /EHsc /std:c++17)
|
||||
|
||||
### /Od
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1837 ms
|
||||
boost::variant (-DONLY_BV): 2627 ms
|
||||
std::variant (-DONLY_SV): 1425 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 9041 ms; S=7.14286e+14
|
||||
variant2: 48367 ms; S=7.14286e+14
|
||||
boost::variant: 102776 ms; S=7.14286e+14
|
||||
std::variant: 40590 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 9029 ms; S=7.14286e+14
|
||||
variant2: 92962 ms; S=7.14286e+14
|
||||
boost::variant: 110441 ms; S=7.14286e+14
|
||||
std::variant: 92974 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### /O2 /DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2571 ms
|
||||
boost::variant (-DONLY_BV): 3335 ms
|
||||
std::variant (-DONLY_SV): 1903 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1949 ms; S=7.14286e+14
|
||||
variant2: 4176 ms; S=7.14286e+14
|
||||
boost::variant: 11312 ms; S=7.14286e+14
|
||||
std::variant: 4617 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1949 ms; S=7.14286e+14
|
||||
variant2: 11807 ms; S=7.14286e+14
|
||||
boost::variant: 15632 ms; S=7.14286e+14
|
||||
std::variant: 10725 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
## g++ 7.4.0 -std=c++17 (Cygwin 64 bit)
|
||||
|
||||
### -O0
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2734 ms
|
||||
boost::variant (-DONLY_BV): 4308 ms
|
||||
std::variant (-DONLY_SV): 2298 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 3620 ms; S=7.14286e+14
|
||||
variant2: 29214 ms; S=7.14286e+14
|
||||
boost::variant: 88492 ms; S=7.14286e+14
|
||||
std::variant: 39510 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 3642 ms; S=7.14286e+14
|
||||
variant2: 75822 ms; S=7.14286e+14
|
||||
boost::variant: 96680 ms; S=7.14286e+14
|
||||
std::variant: 66411 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O1
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2103 ms
|
||||
boost::variant (-DONLY_BV): 3398 ms
|
||||
std::variant (-DONLY_SV): 1841 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1576 ms; S=7.14286e+14
|
||||
variant2: 3424 ms; S=7.14286e+14
|
||||
boost::variant: 4356 ms; S=7.14286e+14
|
||||
std::variant: 3764 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1582 ms; S=7.14286e+14
|
||||
variant2: 9062 ms; S=7.14286e+14
|
||||
boost::variant: 9603 ms; S=7.14286e+14
|
||||
std::variant: 8825 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O2 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2276 ms
|
||||
boost::variant (-DONLY_BV): 3647 ms
|
||||
std::variant (-DONLY_SV): 2111 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1643 ms; S=7.14286e+14
|
||||
variant2: 3070 ms; S=7.14286e+14
|
||||
boost::variant: 3385 ms; S=7.14286e+14
|
||||
std::variant: 3880 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1622 ms; S=7.14286e+14
|
||||
variant2: 8101 ms; S=7.14286e+14
|
||||
boost::variant: 8611 ms; S=7.14286e+14
|
||||
std::variant: 8694 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O3 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2390 ms
|
||||
boost::variant (-DONLY_BV): 3768 ms
|
||||
std::variant (-DONLY_SV): 2094 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1611 ms; S=7.14286e+14
|
||||
variant2: 2975 ms; S=7.14286e+14
|
||||
boost::variant: 3232 ms; S=7.14286e+14
|
||||
std::variant: 3726 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1603 ms; S=7.14286e+14
|
||||
variant2: 8157 ms; S=7.14286e+14
|
||||
boost::variant: 8419 ms; S=7.14286e+14
|
||||
std::variant: 8659 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
## clang++ 5.0.1 -std=c++17 -stdlib=libc++ (Cygwin 64 bit)
|
||||
|
||||
### -O0
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2190 ms
|
||||
boost::variant (-DONLY_BV): 3537 ms
|
||||
std::variant (-DONLY_SV): 2151 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 6063 ms; S=7.14286e+14
|
||||
variant2: 23616 ms; S=7.14286e+14
|
||||
boost::variant: 92730 ms; S=7.14286e+14
|
||||
std::variant: 23160 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 6054 ms; S=7.14286e+14
|
||||
variant2: 52738 ms; S=7.14286e+14
|
||||
boost::variant: 96896 ms; S=7.14286e+14
|
||||
std::variant: 72595 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O1
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2722 ms
|
||||
boost::variant (-DONLY_BV): 4337 ms
|
||||
std::variant (-DONLY_SV): 2697 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 2171 ms; S=7.14286e+14
|
||||
variant2: 9280 ms; S=7.14286e+14
|
||||
boost::variant: 51478 ms; S=7.14286e+14
|
||||
std::variant: 5642 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 2171 ms; S=7.14286e+14
|
||||
variant2: 22166 ms; S=7.14286e+14
|
||||
boost::variant: 54084 ms; S=7.14286e+14
|
||||
std::variant: 14330 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O2 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2499 ms
|
||||
boost::variant (-DONLY_BV): 3826 ms
|
||||
std::variant (-DONLY_SV): 2645 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1604 ms; S=7.14286e+14
|
||||
variant2: 2726 ms; S=7.14286e+14
|
||||
boost::variant: 6662 ms; S=7.14286e+14
|
||||
std::variant: 3869 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1598 ms; S=7.14286e+14
|
||||
variant2: 8136 ms; S=7.14286e+14
|
||||
boost::variant: 9236 ms; S=7.14286e+14
|
||||
std::variant: 6279 ms; S=7.14286e+14
|
||||
```
|
||||
|
||||
### -O3 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 2509 ms
|
||||
boost::variant (-DONLY_BV): 3845 ms
|
||||
std::variant (-DONLY_SV): 2638 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
double: 1592 ms; S=7.14286e+14
|
||||
variant2: 2697 ms; S=7.14286e+14
|
||||
boost::variant: 6648 ms; S=7.14286e+14
|
||||
std::variant: 3826 ms; S=7.14286e+14
|
||||
|
||||
N=100000000:
|
||||
double: 1614 ms; S=7.14286e+14
|
||||
variant2: 8035 ms; S=7.14286e+14
|
||||
boost::variant: 9221 ms; S=7.14286e+14
|
||||
std::variant: 6319 ms; S=7.14286e+14
|
||||
```
|
||||
149
benchmark/benchmark2.cpp
Normal file
149
benchmark/benchmark2.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(ONLY_V2)
|
||||
# define NO_BV
|
||||
# define NO_SV
|
||||
#endif
|
||||
|
||||
#if defined(ONLY_BV)
|
||||
# define NO_V2
|
||||
# define NO_SV
|
||||
#endif
|
||||
|
||||
#if defined(ONLY_SV)
|
||||
# define NO_V2
|
||||
# define NO_BV
|
||||
#endif
|
||||
|
||||
#if !defined(NO_V2)
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(NO_BV)
|
||||
#include <boost/variant.hpp>
|
||||
#endif
|
||||
|
||||
#if !defined(NO_SV)
|
||||
#include <variant>
|
||||
#endif
|
||||
|
||||
#include <type_traits>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
|
||||
struct prefix
|
||||
{
|
||||
int v_;
|
||||
};
|
||||
|
||||
struct X1: prefix {};
|
||||
struct X2: prefix {};
|
||||
struct X3: prefix {};
|
||||
struct X4: prefix {};
|
||||
struct X5: prefix {};
|
||||
struct X6: prefix {};
|
||||
struct X7: prefix {};
|
||||
struct X8: prefix {};
|
||||
struct X9: prefix {};
|
||||
struct X10: prefix {};
|
||||
struct X11: prefix {};
|
||||
struct X12: prefix {};
|
||||
|
||||
inline int get_value( prefix const& v )
|
||||
{
|
||||
return v.v_;
|
||||
}
|
||||
|
||||
#if !defined(NO_V2)
|
||||
|
||||
template<class... T> int get_value( boost::variant2::variant<T...> const& v )
|
||||
{
|
||||
return visit( []( prefix const& x ) { return x.v_; }, v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(NO_BV)
|
||||
|
||||
template<class... T> int get_value( boost::variant<T...> const& v )
|
||||
{
|
||||
return boost::apply_visitor( []( prefix const& x ) { return x.v_; }, v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined(NO_SV)
|
||||
|
||||
template<class... T> int get_value( std::variant<T...> const& v )
|
||||
{
|
||||
return visit( []( prefix const& x ) { return x.v_; }, v );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
template<class V> void test_( int N )
|
||||
{
|
||||
std::vector<V> w;
|
||||
// lack of reserve is deliberate
|
||||
|
||||
auto tp1 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
for( int i = 0; i < N / 12; ++i )
|
||||
{
|
||||
w.push_back( X1{ i } );
|
||||
w.push_back( X2{ i } );
|
||||
w.push_back( X3{ i } );
|
||||
w.push_back( X4{ i } );
|
||||
w.push_back( X5{ i } );
|
||||
w.push_back( X6{ i } );
|
||||
w.push_back( X7{ i } );
|
||||
w.push_back( X8{ i } );
|
||||
w.push_back( X9{ i } );
|
||||
w.push_back( X10{ i } );
|
||||
w.push_back( X11{ i } );
|
||||
w.push_back( X12{ i } );
|
||||
}
|
||||
|
||||
unsigned long long s = 0;
|
||||
|
||||
for( std::size_t i = 0, n = w.size(); i < n; ++i )
|
||||
{
|
||||
s = s + get_value( w[ i ] );
|
||||
}
|
||||
|
||||
auto tp2 = std::chrono::high_resolution_clock::now();
|
||||
|
||||
std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << s << "\n";
|
||||
}
|
||||
|
||||
template<class... T> void test( int N )
|
||||
{
|
||||
std::cout << "N=" << N << ":\n";
|
||||
|
||||
std::cout << " prefix: "; test_<prefix>( N );
|
||||
#if !defined(NO_V2)
|
||||
std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N );
|
||||
#endif
|
||||
#if !defined(NO_BV)
|
||||
std::cout << "boost::variant: "; test_<boost::variant<T...>>( N );
|
||||
#endif
|
||||
#if !defined(NO_SV)
|
||||
std::cout << " std::variant: "; test_<std::variant<T...>>( N );
|
||||
#endif
|
||||
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int const N = 100'000'000;
|
||||
|
||||
test<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12>( N );
|
||||
}
|
||||
207
benchmark/benchmark2.md
Normal file
207
benchmark/benchmark2.md
Normal file
@@ -0,0 +1,207 @@
|
||||
# benchmark2.cpp results
|
||||
|
||||
## VS 2017 15.9.7 64 bit (cl.exe 19.16, /EHsc /std:c++17)
|
||||
|
||||
### /Od
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1403 ms
|
||||
boost::variant (-DONLY_BV): 2972 ms
|
||||
std::variant (-DONLY_SV): 1057 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 7016 ms; S=416666583333336
|
||||
variant2: 24723 ms; S=416666583333336
|
||||
boost::variant: 60438 ms; S=416666583333336
|
||||
std::variant: 20707 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### /O2 /DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1778 ms
|
||||
boost::variant (-DONLY_BV): 3252 ms
|
||||
std::variant (-DONLY_SV): 1372 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 803 ms; S=416666583333336
|
||||
variant2: 2124 ms; S=416666583333336
|
||||
boost::variant: 6191 ms; S=416666583333336
|
||||
std::variant: 2193 ms; S=416666583333336
|
||||
```
|
||||
|
||||
## g++ 7.4.0 -std=c++17 (Cygwin 64 bit)
|
||||
|
||||
### -O0
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1739 ms
|
||||
boost::variant (-DONLY_BV): 3113 ms
|
||||
std::variant (-DONLY_SV): 1719 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 5163 ms; S=416666583333336
|
||||
variant2: 20628 ms; S=416666583333336
|
||||
boost::variant: 43308 ms; S=416666583333336
|
||||
std::variant: 42375 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O1
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1484 ms
|
||||
boost::variant (-DONLY_BV): 2947 ms
|
||||
std::variant (-DONLY_SV): 1448 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 781 ms; S=416666583333336
|
||||
variant2: 1992 ms; S=416666583333336
|
||||
boost::variant: 2249 ms; S=416666583333336
|
||||
std::variant: 4843 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O2 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1547 ms
|
||||
boost::variant (-DONLY_BV): 2999 ms
|
||||
std::variant (-DONLY_SV): 1528 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 793 ms; S=416666583333336
|
||||
variant2: 1686 ms; S=416666583333336
|
||||
boost::variant: 1833 ms; S=416666583333336
|
||||
std::variant: 4340 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O3 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1595 ms
|
||||
boost::variant (-DONLY_BV): 3084 ms
|
||||
std::variant (-DONLY_SV): 1620 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 853 ms; S=416666583333336
|
||||
variant2: 1681 ms; S=416666583333336
|
||||
boost::variant: 1773 ms; S=416666583333336
|
||||
std::variant: 3989 ms; S=416666583333336
|
||||
```
|
||||
|
||||
## clang++ 5.0.1 -std=c++17 -stdlib=libc++ (Cygwin 64 bit)
|
||||
|
||||
### -O0
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1578 ms
|
||||
boost::variant (-DONLY_BV): 2623 ms
|
||||
std::variant (-DONLY_SV): 1508 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 4447 ms; S=416666583333336
|
||||
variant2: 16016 ms; S=416666583333336
|
||||
boost::variant: 42365 ms; S=416666583333336
|
||||
std::variant: 17817 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O1
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1841 ms
|
||||
boost::variant (-DONLY_BV): 2919 ms
|
||||
std::variant (-DONLY_SV): 1776 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 1390 ms; S=416666583333336
|
||||
variant2: 5397 ms; S=416666583333336
|
||||
boost::variant: 23234 ms; S=416666583333336
|
||||
std::variant: 2807 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O2 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1766 ms
|
||||
boost::variant (-DONLY_BV): 2817 ms
|
||||
std::variant (-DONLY_SV): 1718 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 604 ms; S=416666583333336
|
||||
variant2: 1625 ms; S=416666583333336
|
||||
boost::variant: 2735 ms; S=416666583333336
|
||||
std::variant: 2664 ms; S=416666583333336
|
||||
```
|
||||
|
||||
### -O3 -DNDEBUG
|
||||
|
||||
#### Compile time
|
||||
|
||||
```
|
||||
variant2 (-DONLY_V2): 1720 ms
|
||||
boost::variant (-DONLY_BV): 2806 ms
|
||||
std::variant (-DONLY_SV): 1737 ms
|
||||
```
|
||||
|
||||
#### Run time
|
||||
|
||||
```
|
||||
N=100000000:
|
||||
prefix: 603 ms; S=416666583333336
|
||||
variant2: 1608 ms; S=416666583333336
|
||||
boost::variant: 2696 ms; S=416666583333336
|
||||
std::variant: 2668 ms; S=416666583333336
|
||||
```
|
||||
1
doc/.gitignore
vendored
Normal file
1
doc/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/pdf/
|
||||
23
doc/Jamfile
Normal file
23
doc/Jamfile
Normal file
@@ -0,0 +1,23 @@
|
||||
# Copyright 2017, 2018 Peter Dimov
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
import asciidoctor ;
|
||||
|
||||
html variant2.html : variant2.adoc ;
|
||||
|
||||
install html_ : variant2.html : <location>html ;
|
||||
|
||||
pdf variant2.pdf : variant2.adoc ;
|
||||
explicit variant2.pdf ;
|
||||
|
||||
install pdf_ : variant2.pdf : <location>pdf ;
|
||||
explicit pdf_ ;
|
||||
|
||||
###############################################################################
|
||||
alias boostdoc ;
|
||||
explicit boostdoc ;
|
||||
alias boostrelease : html_ ;
|
||||
explicit boostrelease ;
|
||||
2153
doc/html/variant2.html
Normal file
2153
doc/html/variant2.html
Normal file
File diff suppressed because it is too large
Load Diff
5
doc/variant2-docinfo-footer.html
Normal file
5
doc/variant2-docinfo-footer.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<style>
|
||||
|
||||
*:not(pre)>code { background: none; color: #600000; }
|
||||
|
||||
</style>
|
||||
23
doc/variant2.adoc
Normal file
23
doc/variant2.adoc
Normal file
@@ -0,0 +1,23 @@
|
||||
////
|
||||
Copyright 2018 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
# Boost.Variant2: A never valueless variant type
|
||||
Peter Dimov
|
||||
:toc: left
|
||||
:toclevels: 4
|
||||
:idprefix:
|
||||
:docinfo: private-footer
|
||||
|
||||
:leveloffset: +1
|
||||
|
||||
include::variant2/overview.adoc[]
|
||||
include::variant2/reference.adoc[]
|
||||
include::variant2/copyright.adoc[]
|
||||
|
||||
:leveloffset: -1
|
||||
15
doc/variant2/copyright.adoc
Normal file
15
doc/variant2/copyright.adoc
Normal file
@@ -0,0 +1,15 @@
|
||||
////
|
||||
Copyright 2018, 2019 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
[#copyright]
|
||||
# Copyright and License
|
||||
:idprefix:
|
||||
|
||||
This documentation is copyright 2018, 2019 Peter Dimov and is distributed under
|
||||
the http://www.boost.org/LICENSE_1_0.txt[Boost Software License, Version 1.0].
|
||||
40
doc/variant2/overview.adoc
Normal file
40
doc/variant2/overview.adoc
Normal file
@@ -0,0 +1,40 @@
|
||||
////
|
||||
Copyright 2018 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
[#overview]
|
||||
# Overview
|
||||
:idprefix:
|
||||
|
||||
This library implements a type-safe discriminated union (variant) type,
|
||||
`variant<T...>`, that almost conforms to the {cpp}17 Standard's
|
||||
http://en.cppreference.com/w/cpp/utility/variant[`std::variant<T...>`]. The
|
||||
main differences between the two are:
|
||||
|
||||
* `variant<T...>` does not have a valueless-by-exception state;
|
||||
* A converting constructor from, e.g. `variant<int, float>` to
|
||||
`variant<float, double, int>` is provided as an extension;
|
||||
* The reverse operation, going from `variant<float, double, int>` to
|
||||
`variant<int, float>` is provided as the member function `subset<U...>`.
|
||||
(This operation can throw if the current state of the variant cannot be
|
||||
represented.)
|
||||
* `variant<T...>` is not trivial when all contained types are trivial, as
|
||||
mandated by {cpp}17.
|
||||
|
||||
To avoid the valueless-by-exception state, this implementation falls
|
||||
back to using double storage unless
|
||||
|
||||
* one of the alternatives is the type `monostate`,
|
||||
* one of the alternatives has a nonthrowing default constructor, or
|
||||
* all the contained types are nothrow move constructible.
|
||||
|
||||
If the first two bullets don't hold, but the third does, the variant uses
|
||||
single storage, but `emplace` constructs a temporary and moves it into place
|
||||
if the construction of the object can throw. In case this is undesirable, one
|
||||
can force `emplace` into always constructing in-place by adding `monostate` as
|
||||
one of the alternatives.
|
||||
870
doc/variant2/reference.adoc
Normal file
870
doc/variant2/reference.adoc
Normal file
@@ -0,0 +1,870 @@
|
||||
////
|
||||
Copyright 2018, 2019 Peter Dimov
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
////
|
||||
|
||||
[#reference]
|
||||
# Reference
|
||||
:idprefix: ref_
|
||||
|
||||
## <boost/variant2/variant.hpp>
|
||||
|
||||
### Synopsis
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
namespace variant2 {
|
||||
|
||||
// in_place_type
|
||||
|
||||
template<class T> struct in_place_type_t {};
|
||||
template<class T> constexpr in_place_type_t<T> in_place_type{};
|
||||
|
||||
// in_place_index
|
||||
|
||||
template<std::size_t I> struct in_place_index_t {};
|
||||
template<std::size_t I> constexpr in_place_index_t<I> in_place_index{};
|
||||
|
||||
// variant
|
||||
|
||||
template<class... T> class variant;
|
||||
|
||||
// variant_size
|
||||
|
||||
template<class T> struct variant_size {};
|
||||
|
||||
template<class T> struct variant_size<T const>: variant_size<T> {};
|
||||
template<class T> struct variant_size<T volatile>: variant_size<T> {};
|
||||
template<class T> struct variant_size<T const volatile>: variant_size<T> {};
|
||||
|
||||
template<class T> struct variant_size<T&>: variant_size<T> {}; // extension
|
||||
template<class T> struct variant_size<T&&>: variant_size<T> {}; // extension
|
||||
|
||||
template<class T>
|
||||
inline constexpr size_t variant_size_v = variant_size<T>::value;
|
||||
|
||||
template<class... T>
|
||||
struct variant_size<variant<T...>>:
|
||||
std::integral_constant<std::size_t, sizeof...(T)> {};
|
||||
|
||||
// variant_alternative
|
||||
|
||||
template<size_t I, class T> struct variant_alternative {};
|
||||
|
||||
template<size_t I, class T> struct variant_alternative<I, T const>;
|
||||
template<size_t I, class T> struct variant_alternative<I, T volatile>;
|
||||
template<size_t I, class T> struct variant_alternative<I, T const volatile>;
|
||||
|
||||
template<size_t I, class T> struct variant_alternative<I, T&>; // extension
|
||||
template<size_t I, class T> struct variant_alternative<I, T&&>; // extension
|
||||
|
||||
template<size_t I, class T>
|
||||
using variant_alternative_t = typename variant_alternative<I, T>::type;
|
||||
|
||||
template<size_t I, class... T>
|
||||
struct variant_alternative<I, variant<T...>>;
|
||||
|
||||
// variant_npos
|
||||
|
||||
constexpr std::size_t variant_npos = -1;
|
||||
|
||||
// holds_alternative
|
||||
|
||||
template<class U, class... T>
|
||||
constexpr bool holds_alternative(const variant<T...>& v) noexcept;
|
||||
|
||||
// get
|
||||
|
||||
template<size_t I, class... T>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
get(variant<T...>& v);
|
||||
template<size_t I, class... T>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&&
|
||||
get(variant<T...>&& v);
|
||||
template<size_t I, class... T>
|
||||
constexpr const variant_alternative_t<I, variant<T...>>&
|
||||
get(const variant<T...>& v);
|
||||
template<size_t I, class... T>
|
||||
constexpr const variant_alternative_t<I, variant<T...>>&&
|
||||
get(const variant<T...>&& v);
|
||||
|
||||
template<class U, class... T>
|
||||
constexpr U& get(variant<T...>& v);
|
||||
template<class U, class... T>
|
||||
constexpr U&& get(variant<T...>&& v);
|
||||
template<class U, class... T>
|
||||
constexpr const U& get(const variant<T...>& v);
|
||||
template<class U, class... T>
|
||||
constexpr const U&& get(const variant<T...>&& v);
|
||||
|
||||
// get_if
|
||||
|
||||
template<size_t I, class... T>
|
||||
constexpr add_pointer_t<variant_alternative_t<I, variant<T...>>>
|
||||
get_if(variant<T...>* v) noexcept;
|
||||
template<size_t I, class... T>
|
||||
constexpr add_pointer_t<const variant_alternative_t<I, variant<T...>>>
|
||||
get_if(const variant<T...>* v) noexcept;
|
||||
|
||||
template<class U, class... T>
|
||||
constexpr add_pointer_t<U>
|
||||
get_if(variant<T...>* v) noexcept;
|
||||
template<class U, class... T>
|
||||
constexpr add_pointer_t<const U>
|
||||
get_if(const variant<T...>* v) noexcept;
|
||||
|
||||
// relational operators
|
||||
|
||||
template<class... T>
|
||||
constexpr bool operator==(const variant<T...>& v, const variant<T...>& w);
|
||||
template<class... T>
|
||||
constexpr bool operator!=(const variant<T...>& v, const variant<T...>& w);
|
||||
template<class... T>
|
||||
constexpr bool operator<(const variant<T...>& v, const variant<T...>& w);
|
||||
template<class... T>
|
||||
constexpr bool operator>(const variant<T...>& v, const variant<T...>& w);
|
||||
template<class... T>
|
||||
constexpr bool operator<=(const variant<T...>& v, const variant<T...>& w);
|
||||
template<class... T>
|
||||
constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w);
|
||||
|
||||
// visit
|
||||
|
||||
template<class F, class... V>
|
||||
constexpr /*see below*/ visit(F&& f, V&&... v);
|
||||
|
||||
// monostate
|
||||
|
||||
struct monostate {};
|
||||
|
||||
constexpr bool operator==(monostate, monostate) noexcept { return true; }
|
||||
constexpr bool operator!=(monostate, monostate) noexcept { return false; }
|
||||
constexpr bool operator<(monostate, monostate) noexcept { return false; }
|
||||
constexpr bool operator>(monostate, monostate) noexcept { return false; }
|
||||
constexpr bool operator<=(monostate, monostate) noexcept { return true; }
|
||||
constexpr bool operator>=(monostate, monostate) noexcept { return true; }
|
||||
|
||||
// swap
|
||||
|
||||
template<class... T>
|
||||
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
|
||||
|
||||
// bad_variant_access
|
||||
|
||||
class bad_variant_access;
|
||||
|
||||
} // namespace variant2
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
### variant
|
||||
|
||||
```
|
||||
namespace boost {
|
||||
namespace variant2 {
|
||||
|
||||
template<class... T> class variant
|
||||
{
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
constexpr variant() noexcept( /*see below*/ );
|
||||
|
||||
constexpr variant( variant const & r ) noexcept( /*see below*/ );
|
||||
constexpr variant( variant&& r ) noexcept( /*see below*/ );
|
||||
|
||||
template<class U>
|
||||
constexpr variant( U&& u ) noexcept( /*see below*/ );
|
||||
|
||||
template<class U, class... A>
|
||||
constexpr explicit variant( in_place_type_t<U>, A&&... a );
|
||||
template<class U, class V, class... A>
|
||||
constexpr explicit variant( in_place_type_t<U>,
|
||||
std::initializer_list<V> il, A&&... a );
|
||||
|
||||
template<size_t I, class... A>
|
||||
constexpr explicit variant( in_place_index_t<I>, A&&... a );
|
||||
template<size_t I, class V, class... A>
|
||||
constexpr explicit variant( in_place_index_t<I>,
|
||||
std::initializer_list<V> il, A&&... a );
|
||||
|
||||
// destructor
|
||||
|
||||
~variant();
|
||||
|
||||
// assignment
|
||||
|
||||
constexpr variant& operator=( variant const & r ) noexcept( /*see below*/ );
|
||||
constexpr variant& operator=( variant&& r ) noexcept( /*see below*/ );
|
||||
|
||||
template<class U> constexpr variant& operator=( U&& u ) noexcept( /*see below*/ );
|
||||
|
||||
// modifiers
|
||||
|
||||
template<class U, class... A>
|
||||
constexpr U& emplace( A&&... a );
|
||||
template<class U, class V, class... A>
|
||||
constexpr U& emplace( std::initializer_list<V> il, A&&... a );
|
||||
|
||||
template<size_t I, class... A>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
emplace( A&&... a );
|
||||
template<size_t I, class V, class... A>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
emplace( std::initializer_list<V> il, A&&... a );
|
||||
|
||||
// value status
|
||||
|
||||
constexpr bool valueless_by_exception() const noexcept;
|
||||
constexpr size_t index() const noexcept;
|
||||
|
||||
// swap
|
||||
|
||||
void swap( variant& r ) noexcept( /*see below*/ );
|
||||
|
||||
// converting constructors (extension)
|
||||
|
||||
template<class... U> variant( variant<U...> const& r )
|
||||
noexcept( /*see below*/ );
|
||||
|
||||
template<class... U> variant( variant<U...>&& r )
|
||||
noexcept( /*see below*/ );
|
||||
|
||||
// subset (extension)
|
||||
|
||||
template<class... U> constexpr variant<U...> subset() & ;
|
||||
template<class... U> constexpr variant<U...> subset() && ;
|
||||
template<class... U> constexpr variant<U...> subset() const& ;
|
||||
template<class... U> constexpr variant<U...> subset() const&& ;
|
||||
};
|
||||
|
||||
} // namespace variant2
|
||||
} // namespace boost
|
||||
```
|
||||
|
||||
#### Constructors
|
||||
|
||||
```
|
||||
constexpr variant() noexcept( std::is_nothrow_default_constructible_v<T0> );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Constructs a `variant` holding a value-initialized value of
|
||||
type `T0`.
|
||||
Ensures: :: `index() == 0`.
|
||||
Throws: :: Any exception thrown by the value-initialization of `T0`.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
`std::is_default_constructible_v<T0>` is `true`.
|
||||
|
||||
```
|
||||
constexpr variant( variant const & w )
|
||||
noexcept( mp_all<std::is_nothrow_copy_constructible<T>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the variant to hold the same alternative and value as
|
||||
`w`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
`std::is_copy_constructible_v<Ti>` is `true` for all `i`.
|
||||
|
||||
```
|
||||
constexpr variant( variant&& w )
|
||||
noexcept( mp_all<std::is_nothrow_move_constructible<T>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the variant to hold the same alternative and value as
|
||||
`w`.
|
||||
Throws: :: Any exception thrown by the move-initialization of the contained
|
||||
value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
`std::is_move_constructible_v<Ti>` is `true` for all `i`.
|
||||
|
||||
```
|
||||
template<class U> constexpr variant( U&& u ) noexcept(/*see below*/);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `Tj` be a type that is determined as follows: build an imaginary function
|
||||
`FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by
|
||||
overload resolution for the expression `FUN(std::forward<U>(u))` defines the
|
||||
alternative `Tj` which is the type of the contained value after construction.
|
||||
|
||||
Effects: :: Initializes `*this` to hold the alternative type `Tj` and
|
||||
initializes the contained value from `std::forward<U>(u)`.
|
||||
Ensures: :: `holds_alternative<Tj>(*this)`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: The expression inside `noexcept` is equivalent to
|
||||
`std::is_nothrow_constructible_v<Tj, U>`. This function does not participate in
|
||||
overload resolution unless
|
||||
- `sizeof...(T)` is nonzero,
|
||||
- `std::is_same_v<std::remove_cvref_t<U>, variant>` is `false`,
|
||||
- `std::remove_cvref_t<U>` is neither a specialization of `in_place_type_t` nor a
|
||||
specialization of `in_place_index_t`,
|
||||
- `std::is_constructible_v<Tj, U>` is `true`, and
|
||||
- the expression `FUN(std::forward<U>(u))` is well-formed.
|
||||
|
||||
```
|
||||
template<class U, class... A>
|
||||
constexpr explicit variant( in_place_type_t<U>, A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value of type `U` with the arguments
|
||||
`std::forward<A>(a)...`.
|
||||
Ensures: :: `holds_alternative<U>(*this)`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
there is exactly one occurrence of `U` in `T...` and
|
||||
`std::is_constructible_v<U, A...>` is true.
|
||||
|
||||
```
|
||||
template<class U, class V, class... A>
|
||||
constexpr explicit variant( in_place_type_t<U>, std::initializer_list<V> il,
|
||||
A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value of type `U` with the arguments `il`,
|
||||
`std::forward<A>(a)...`.
|
||||
Ensures: :: `holds_alternative<U>(*this)`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
there is exactly one occurrence of `U` in `T...` and
|
||||
`std::is_constructible_v<U, initializer_list<V>&, A...>` is `true`.
|
||||
|
||||
```
|
||||
template<size_t I, class... A>
|
||||
constexpr explicit variant( in_place_index_t<I>, A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value of type `TI` with the arguments
|
||||
`std::forward<A>(a)...`.
|
||||
Ensures: :: `index() == I`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
`I < sizeof...(T)` and `std::is_constructible_v<TI, A...>` is `true`.
|
||||
|
||||
```
|
||||
template<size_t I, class V, class... A>
|
||||
constexpr explicit variant( in_place_index_t<I>, std::initializer_list<V> il,
|
||||
A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value of type `TI` with the arguments
|
||||
`il`, `std::forward<A>(a)...`.
|
||||
Ensures: :: `index() == I`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
`I < sizeof...(T)` and
|
||||
`std::is_constructible_v<TI, initializer_list<V>&, A...>` is `true`.
|
||||
|
||||
#### Destructor
|
||||
|
||||
```
|
||||
~variant();
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Destroys the currently contained value.
|
||||
|
||||
#### Assignment
|
||||
|
||||
```
|
||||
constexpr variant& operator=( const variant& r )
|
||||
noexcept( mp_all<std::is_nothrow_copy_constructible<T>...,
|
||||
std::is_nothrow_copy_assignable<T>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `j` be `r.index()`.
|
||||
|
||||
Effects: ::
|
||||
- If `index() == j`, assigns the value contained in `r` to the value
|
||||
contained in `*this`.
|
||||
- Otherwise, equivalent to `emplace<j>(get<j>(r))`.
|
||||
Returns: :: `*this`.
|
||||
Ensures: :: `index() == r.index()`.
|
||||
Remarks: :: This operator does not participate in overload resolution unless
|
||||
`std::is_copy_constructible_v<Ti> && std::is_copy_assignable_v<Ti>` is
|
||||
`true` for all `i`.
|
||||
|
||||
```
|
||||
constexpr variant& operator=( variant&& r )
|
||||
noexcept( mp_all<std::is_nothrow_move_constructible<T>...,
|
||||
std::is_nothrow_move_assignable<T>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `j` be `r.index()`.
|
||||
|
||||
Effects: ::
|
||||
- If `index() == j`, assigns the value contained in `std::move(r)` to the
|
||||
value contained in `*this`.
|
||||
- Otherwise, equivalent to `emplace<j>(get<j>(std::move(r)))`.
|
||||
Returns: :: `*this`.
|
||||
Ensures: :: `index() == r.index()`.
|
||||
Remarks: :: This operator does not participate in overload resolution unless
|
||||
`std::is_move_constructible_v<Ti> && std::is_move_assignable_v<Ti>` is
|
||||
`true` for all `i`.
|
||||
|
||||
```
|
||||
template<class U> constexpr variant& operator=( U&& u )
|
||||
noexcept( /*see below*/ );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `Tj` be a type that is determined as follows: build an imaginary function
|
||||
`FUN(Ti)` for each alternative type `Ti`. The overload `FUN(Tj)` selected by
|
||||
overload resolution for the expression `FUN(std::forward<U>(u))` defines the
|
||||
alternative `Tj` which is the type of the contained value after construction.
|
||||
|
||||
Effects: ::
|
||||
- If `index() == j`, assigns `std::forward<U>(u)` to the value contained in
|
||||
`*this`.
|
||||
- Otherwise, equivalent to `emplace<j>(std::forward<U>(u))`.
|
||||
Returns: :: `*this`.
|
||||
Ensures: :: `index() == j`.
|
||||
Remarks: ::
|
||||
The expression inside `noexcept` is `std::is_nothrow_constructible_v<Tj, U>
|
||||
&& std::is_nothrow_assignable_v<Tj&, U>`.
|
||||
This operator does not participate in overload resolution unless
|
||||
- `std::is_same_v<std::remove_cvref_t<T>, variant>` is `false`,
|
||||
- `std::is_constructible_v<Tj, U> && std::is_assignable_v<Tj&, U>` is
|
||||
`true`, and
|
||||
- the expression `FUN(std::forward<U>(u))` (with `FUN` being the
|
||||
above-mentioned set of imaginary functions) is well-formed.
|
||||
|
||||
#### Modifiers
|
||||
|
||||
```
|
||||
template<class U, class... A>
|
||||
constexpr U& emplace( A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `I` be the zero-based index of `U` in `T...`.
|
||||
|
||||
Effects: :: Equivalent to: `return emplace<I>(std::forward<A>(a)...);`
|
||||
Remarks: ::
|
||||
This function shall not participate in overload resolution unless
|
||||
`std::is_constructible_v<U, A...>` is `true` and `U` occurs exactly once
|
||||
in `T...`.
|
||||
|
||||
```
|
||||
template<class U, class V, class... A>
|
||||
constexpr U& emplace( std::initializer_list<V> il, A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Let `I` be the zero-based index of `U` in `T...`.
|
||||
|
||||
Effects: :: Equivalent to: `return emplace<I>(il, std::forward<A>(a)...);`
|
||||
Remarks: ::
|
||||
This function shall not participate in overload resolution unless
|
||||
`std::is_constructible_v<U, std::initializer_list<V>&, A...>` is `true`
|
||||
and `U` occurs exactly once in `T...`.
|
||||
|
||||
|
||||
```
|
||||
template<size_t I, class... A>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
emplace( A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: `I < sizeof(T...)`.
|
||||
Effects: ::
|
||||
Destroys the currently contained value, then initializes a new contained
|
||||
value as if using the expression `Ti(std::forward<A>(a)...)`.
|
||||
Ensures: :: `index() == I`.
|
||||
Returns: :: A reference to the new contained value.
|
||||
Remarks: ::
|
||||
This function shall not participate in overload resolution unless
|
||||
`std::is_constructible_v<Ti, A...>` is `true`.
|
||||
|
||||
```
|
||||
template<size_t I, class V, class... A>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
emplace( std::initializer_list<V> il, A&&... a );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: `I < sizeof(T...)`.
|
||||
Effects: ::
|
||||
Destroys the currently contained value, then initializes a new contained
|
||||
value as if using the expression `Ti(il, std::forward<A>(a)...)`.
|
||||
Ensures: :: `index() == I`.
|
||||
Returns: :: A reference to the new contained value.
|
||||
Remarks: ::
|
||||
This function shall not participate in overload resolution unless
|
||||
`std::is_constructible_v<Ti, std::initializer_list<V>&, A...>` is `true`.
|
||||
|
||||
#### Value Status
|
||||
|
||||
```
|
||||
constexpr bool valueless_by_exception() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `false`.
|
||||
|
||||
```
|
||||
constexpr size_t index() const noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: The zero-based index of the active alternative.
|
||||
|
||||
#### Swap
|
||||
|
||||
```
|
||||
void swap( variant& r ) noexcept( mp_all<std::is_nothrow_move_constructible<T>...,
|
||||
is_nothrow_swappable<T>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: ::
|
||||
- If `index() == r.index()`, calls `swap(get<I>(*this), get<I>(r))`,
|
||||
where `I` is `index()`.
|
||||
- Otherwise, as if
|
||||
`variant tmp(std::move(*this)); *this = std::move(r); r = std::move(tmp);`
|
||||
|
||||
#### Converting Constructors (extension)
|
||||
|
||||
```
|
||||
template<class... U> variant( variant<U...> const& r )
|
||||
noexcept( mp_all<std::is_nothrow_copy_constructible<U>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value from the contained value of `r`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
all types in `U...` are in `T...` and
|
||||
`std::is_copy_constructible_v<Ui>::value` is `true` for all `Ui`.
|
||||
|
||||
```
|
||||
template<class... U> variant( variant<U...>&& r )
|
||||
noexcept( mp_all<std::is_nothrow_move_constructible<U>...>::value );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Initializes the contained value from the contained value of
|
||||
`std::move(r)`.
|
||||
Throws: :: Any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
all types in `U...` are in `T...` and
|
||||
`std::is_move_constructible_v<Ui>::value` is `true` for all `Ui`.
|
||||
|
||||
#### Subset (extension)
|
||||
|
||||
```
|
||||
template<class... U> constexpr variant<U...> subset() & ;
|
||||
```
|
||||
```
|
||||
template<class... U> constexpr variant<U...> subset() const& ;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: A `variant<U...>` whose contained value is copy-initialized from
|
||||
the contained value of `*this` and has the same type.
|
||||
Throws: ::
|
||||
- If the active alternative of `*this` is not among the types in `U...`,
|
||||
`bad_variant_access`.
|
||||
- Otherwise, any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
all types in `U...` are in `T...` and
|
||||
`std::is_copy_constructible_v<Ui>::value` is `true` for all `Ui`.
|
||||
|
||||
```
|
||||
template<class... U> constexpr variant<U...> subset() && ;
|
||||
```
|
||||
```
|
||||
template<class... U> constexpr variant<U...> subset() const&& ;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: A `variant<U...>` whose contained value is move-initialized from
|
||||
the contained value of `*this` and has the same type.
|
||||
Throws: ::
|
||||
- If the active alternative of `*this` is not among the types in `U...`,
|
||||
`bad_variant_access`.
|
||||
- Otherwise, any exception thrown by the initialization of the contained value.
|
||||
Remarks: :: This function does not participate in overload resolution unless
|
||||
all types in `U...` are in `T...` and
|
||||
`std::is_move_constructible_v<Ui>::value` is `true` for all `Ui`.
|
||||
|
||||
### variant_alternative
|
||||
|
||||
```
|
||||
template<size_t I, class T> struct variant_alternative<I, T const>;
|
||||
```
|
||||
```
|
||||
template<size_t I, class T> struct variant_alternative<I, T volatile>;
|
||||
```
|
||||
```
|
||||
template<size_t I, class T> struct variant_alternative<I, T const volatile>;
|
||||
```
|
||||
```
|
||||
template<size_t I, class T> struct variant_alternative<I, T&>; // extension
|
||||
```
|
||||
```
|
||||
template<size_t I, class T> struct variant_alternative<I, T&&>; // extension
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
--
|
||||
If `typename variant_alternative<I, T>::type` exists and is `U`,
|
||||
|
||||
* `variant_alternative<I, T const>::type` is `U const`;
|
||||
* `variant_alternative<I, T volatile>::type` is `U volatile`;
|
||||
* `variant_alternative<I, T const volatile>::type` is `U const volatile`.
|
||||
* `variant_alternative<I, T&>::type` is `U&`.
|
||||
* `variant_alternative<I, T&&>::type` is `U&&`.
|
||||
|
||||
Otherwise, these structs have no member `type`.
|
||||
--
|
||||
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
struct variant_alternative<I, variant<T...>>;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
When `I < sizeof...(T)`, the nested type `type` is an alias for the `I`-th
|
||||
(zero-based) type in `T...`. Otherwise, there is no member `type`.
|
||||
|
||||
### holds_alternative
|
||||
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr bool holds_alternative(const variant<T...>& v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the
|
||||
program is ill-formed.
|
||||
Returns: :: `true` if `index()` is equal to the zero-based index of `U`
|
||||
in `T...`.
|
||||
|
||||
### get
|
||||
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&
|
||||
get(variant<T...>& v);
|
||||
```
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr variant_alternative_t<I, variant<T...>>&&
|
||||
get(variant<T...>&& v);
|
||||
```
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr const variant_alternative_t<I, variant<T...>>&
|
||||
get(const variant<T...>& v);
|
||||
```
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr const variant_alternative_t<I, variant<T...>>&&
|
||||
get(const variant<T...>&& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: If `v.index()` is `I`, returns a reference to the object stored in
|
||||
the variant. Otherwise, throws `bad_variant_access`.
|
||||
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr U& get(variant<T...>& v);
|
||||
```
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr U&& get(variant<T...>&& v);
|
||||
```
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr const U& get(const variant<T...>& v);
|
||||
```
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr const U&& get(const variant<T...>&& v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the
|
||||
program is ill-formed.
|
||||
Effects: :: If `v` holds a value of type `U`, returns a reference to that value.
|
||||
Otherwise, throws `bad_variant_access`.
|
||||
|
||||
### get_if
|
||||
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr add_pointer_t<variant_alternative_t<I, variant<T...>>>
|
||||
get_if(variant<T...>* v) noexcept;
|
||||
```
|
||||
```
|
||||
template<size_t I, class... T>
|
||||
constexpr add_pointer_t<const variant_alternative_t<I, variant<T...>>>
|
||||
get_if(const variant<T...>* v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: `I < sizeof...(U)`. Otherwise, the program is ill-formed.
|
||||
Effects: :: A pointer to the value stored in the variant, if
|
||||
`v != nullptr && v\->index() == I`. Otherwise, `nullptr`.
|
||||
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr add_pointer_t<U>
|
||||
get_if(variant<T...>* v) noexcept;
|
||||
```
|
||||
```
|
||||
template<class U, class... T>
|
||||
constexpr add_pointer_t<const U>
|
||||
get_if(const variant<T...>* v) noexcept;
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Requires: :: The type `U` occurs exactly once in `T...`. Otherwise, the
|
||||
program is ill-formed.
|
||||
Effects: :: Equivalent to: `return get_if<I>(v);` with `I` being
|
||||
the zero-based index of `U` in `T...`.
|
||||
|
||||
### Relational Operators
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator==(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `v.index() == w.index && get<I>(v) == get<I>(w)`, where `I`
|
||||
is `v.index()`.
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator!=(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `!(v == w)`.
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator<(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `v.index() < w.index || (v.index() == w.index && get<I>(v) < get<I>(w))`,
|
||||
where `I` is `v.index()`.
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator>(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `w < v`.
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator<=(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `v.index() < w.index || (v.index() == w.index && get<I>(v) \<= get<I>(w))`,
|
||||
where `I` is `v.index()`.
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
constexpr bool operator>=(const variant<T...>& v, const variant<T...>& w);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `w \<= v`.
|
||||
|
||||
### visit
|
||||
|
||||
```
|
||||
template<class F, class... V>
|
||||
constexpr /*see below*/ visit(F&& f, V&&... v);
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Returns: :: `std::forward<F>(f)(get<I>(std::forward<V>(v))...)`, where
|
||||
`I...` is `v.index()...`.
|
||||
|
||||
### swap
|
||||
|
||||
```
|
||||
template<class... T>
|
||||
void swap(variant<T...>& v, variant<T...>& w) noexcept( /*see below*/ );
|
||||
```
|
||||
[none]
|
||||
* {blank}
|
||||
+
|
||||
Effects: :: Equivalent to `v.swap(w)`.
|
||||
|
||||
### bad_variant_access
|
||||
|
||||
```
|
||||
class bad_variant_access: public std::exception
|
||||
{
|
||||
public:
|
||||
|
||||
bad_variant_access() noexcept = default;
|
||||
|
||||
char const * what() const noexcept
|
||||
{
|
||||
return "bad_variant_access";
|
||||
}
|
||||
};
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
15
index.html
Normal file
15
index.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="refresh" content="0; URL=doc/html/variant2.html">
|
||||
</head>
|
||||
<body>
|
||||
Automatic redirection failed, please go to
|
||||
<a href="doc/html/mp11.html">doc/html/variant2.html</a>.
|
||||
</body>
|
||||
</html>
|
||||
<!--
|
||||
Copyright Beman Dawes, 2001
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
See accompanying file LICENSE_1_0.txt or copy at
|
||||
http://www.boost.org/LICENSE_1_0.txt
|
||||
-->
|
||||
19
test/Jamfile
19
test/Jamfile
@@ -27,10 +27,10 @@ run variant_default_construct.cpp ;
|
||||
compile variant_default_construct_cx.cpp ;
|
||||
|
||||
run variant_copy_construct.cpp ;
|
||||
compile variant_copy_construct_cx.cpp ;
|
||||
compile variant_copy_construct_cx.cpp : <toolset>msvc-14.0:<build>no ;
|
||||
|
||||
run variant_move_construct.cpp ;
|
||||
compile variant_move_construct_cx.cpp ;
|
||||
compile variant_move_construct_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
|
||||
run variant_value_construct.cpp ;
|
||||
compile variant_value_construct_cx.cpp ;
|
||||
@@ -57,10 +57,23 @@ run variant_emplace_type.cpp ;
|
||||
compile variant_emplace_type_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
|
||||
run variant_swap.cpp ;
|
||||
|
||||
run variant_eq_ne.cpp ;
|
||||
compile variant_eq_ne_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
|
||||
run variant_lt_gt.cpp ;
|
||||
compile variant_lt_gt_cx.cpp : [ requires cxx14_constexpr ] ;
|
||||
|
||||
run variant_destroy.cpp ;
|
||||
run variant_visit.cpp ;
|
||||
run variant_lt_gt.cpp ;
|
||||
|
||||
run variant_convert_construct.cpp ;
|
||||
run variant_subset.cpp ;
|
||||
run variant_valueless.cpp ;
|
||||
|
||||
run variant_copy_construct_throw.cpp ;
|
||||
run variant_move_construct_throw.cpp ;
|
||||
run variant_convert_construct_throw.cpp ;
|
||||
|
||||
run variant_copy_assign_throw.cpp ;
|
||||
run variant_move_assign_throw.cpp ;
|
||||
|
||||
@@ -25,65 +25,130 @@ int main()
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void> volatile>, void volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void> const volatile>, void const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char>&>, char&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char> const&>, char const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char>&&>, char&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char> const&&>, char const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int>>, void>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> const>, void const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> volatile>, void volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int> const volatile>, void const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int>&>, char&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int> const&>, char const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int>&&>, char&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int> const&&>, char const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>>, int>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const>, int const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> volatile>, int volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const volatile>, int const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>&>, int&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const&>, int const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int>&&>, int&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int> const&&>, int const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float>>, void>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> const>, void const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> volatile>, void volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<void, int, float> const volatile>, void const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float>&>, char&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float> const&>, char const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float>&&>, char&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<0, variant<char, int, float> const&&>, char const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>>, int>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const>, int const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> volatile>, int volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const volatile>, int const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>&>, int&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const&>, int const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float>&&>, int&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<1, variant<void, int, float> const&&>, int const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>>, float>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const>, float const>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> volatile>, float volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const volatile>, float const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>&>, float&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const&>, float const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float>&&>, float&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((std::is_same<variant_alternative_t<2, variant<void, int, float> const&&>, float const&&>));
|
||||
|
||||
variant_alternative<0, void>();
|
||||
variant_alternative<0, void const>();
|
||||
variant_alternative<0, void volatile>();
|
||||
variant_alternative<0, void const volatile>();
|
||||
|
||||
variant_alternative<0, int&>();
|
||||
variant_alternative<0, int const&>();
|
||||
variant_alternative<0, int&&>();
|
||||
variant_alternative<0, int const&&>();
|
||||
|
||||
variant_alternative<0, variant<>>();
|
||||
variant_alternative<0, variant<> const>();
|
||||
variant_alternative<0, variant<> volatile>();
|
||||
variant_alternative<0, variant<> const volatile>();
|
||||
|
||||
variant_alternative<0, variant<>&>();
|
||||
variant_alternative<0, variant<> const&>();
|
||||
variant_alternative<0, variant<>&&>();
|
||||
variant_alternative<0, variant<> const&&>();
|
||||
|
||||
variant_alternative<1, variant<int>>();
|
||||
variant_alternative<1, variant<int> const>();
|
||||
variant_alternative<1, variant<int> volatile>();
|
||||
variant_alternative<1, variant<int> const volatile>();
|
||||
|
||||
variant_alternative<1, variant<int>&>();
|
||||
variant_alternative<1, variant<int> const&>();
|
||||
variant_alternative<1, variant<int>&&>();
|
||||
variant_alternative<1, variant<int> const&&>();
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void const>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void volatile>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, void const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, int const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> volatile>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<>&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<0>, variant<> const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int>&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_alt_t, mp_size_t<0>, variant<int> const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> volatile>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int>&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_alt_t, mp_size_t<1>, variant<int> const&&>));
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
91
test/variant_convert_construct_throw.cpp
Normal file
91
test/variant_convert_construct_throw.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct X
|
||||
{
|
||||
static int instances;
|
||||
|
||||
X()
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
X( X const& )
|
||||
{
|
||||
throw std::runtime_error( "X(X const&)" );
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
};
|
||||
|
||||
int X::instances = 0;
|
||||
|
||||
void test_copy()
|
||||
{
|
||||
X::instances = 0;
|
||||
|
||||
{
|
||||
variant<X> v1;
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
|
||||
try
|
||||
{
|
||||
variant<X, int, float> v2( v1 );
|
||||
BOOST_TEST_EQ( X::instances, 2 );
|
||||
}
|
||||
catch( std::exception const& )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 0 );
|
||||
}
|
||||
|
||||
void test_move()
|
||||
{
|
||||
X::instances = 0;
|
||||
|
||||
{
|
||||
variant<X> v1;
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
|
||||
try
|
||||
{
|
||||
variant<X, int, float> v2( std::move( v1 ) );
|
||||
BOOST_TEST_EQ( X::instances, 2 );
|
||||
}
|
||||
catch( std::exception const& )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 0 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_copy();
|
||||
test_move();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
51
test/variant_copy_assign_throw.cpp
Normal file
51
test/variant_copy_assign_throw.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct Y1
|
||||
{
|
||||
Y1() noexcept {} // =default fails on msvc-14.0
|
||||
|
||||
Y1(Y1 const&)
|
||||
{
|
||||
throw std::runtime_error( "Y1(Y1 const&)" );
|
||||
}
|
||||
|
||||
Y1& operator=(Y1 const&) = default;
|
||||
};
|
||||
|
||||
struct Y2
|
||||
{
|
||||
Y2() noexcept {}
|
||||
|
||||
Y2(Y2 const&)
|
||||
{
|
||||
throw std::runtime_error( "Y2(Y2 const&)" );
|
||||
}
|
||||
|
||||
Y2& operator=(Y2 const&) = default;
|
||||
};
|
||||
|
||||
void test()
|
||||
{
|
||||
variant<Y1, Y2> v1( in_place_type_t<Y1>{} );
|
||||
variant<Y1, Y2> v2( in_place_type_t<Y2>{} );
|
||||
|
||||
BOOST_TEST_THROWS( v1 = v2, std::runtime_error )
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -68,6 +68,16 @@ int main()
|
||||
test( variant<int, float>(1) );
|
||||
test( variant<int, float>(3.14f) );
|
||||
|
||||
test( variant<int const, float const>() );
|
||||
test( variant<int const, float const>(1) );
|
||||
test( variant<int const, float const>(3.14f) );
|
||||
|
||||
test( variant<std::string>() );
|
||||
test( variant<std::string>("test") );
|
||||
|
||||
test( variant<std::string const>() );
|
||||
test( variant<std::string const>("test") );
|
||||
|
||||
test( variant<int, float, std::string>() );
|
||||
test( variant<int, float, std::string>(1) );
|
||||
test( variant<int, float, std::string>(3.14f) );
|
||||
@@ -84,6 +94,8 @@ int main()
|
||||
|
||||
test( variant<std::string, std::string, float>() );
|
||||
|
||||
test( variant<X1 const>() );
|
||||
|
||||
test( variant<X1, X2>() );
|
||||
test( variant<X1, X2, int>() );
|
||||
test( variant<X1, X2, X2>() );
|
||||
|
||||
@@ -6,13 +6,6 @@
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603
|
||||
|
||||
// no constexpr lambda support
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
|
||||
using namespace boost::variant2;
|
||||
@@ -40,10 +33,9 @@ enum E
|
||||
|
||||
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
|
||||
template<class T, class V> constexpr T test( V const& v )
|
||||
template<class T, class V> constexpr T test( V const v )
|
||||
{
|
||||
V v2( v );
|
||||
return get<T>(v);
|
||||
return get<T>( v );
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -118,5 +110,3 @@ int main()
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // constexpr lambda support
|
||||
|
||||
65
test/variant_copy_construct_throw.cpp
Normal file
65
test/variant_copy_construct_throw.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct X
|
||||
{
|
||||
static int instances;
|
||||
|
||||
X()
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
X( X const& )
|
||||
{
|
||||
throw std::runtime_error( "X(X const&)" );
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
};
|
||||
|
||||
int X::instances = 0;
|
||||
|
||||
void test()
|
||||
{
|
||||
X::instances = 0;
|
||||
|
||||
{
|
||||
variant<X> v1;
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
|
||||
try
|
||||
{
|
||||
variant<X> v2( v1 );
|
||||
BOOST_TEST_EQ( X::instances, 2 );
|
||||
}
|
||||
catch( std::exception const& )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 0 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
return boost::report_errors();
|
||||
}
|
||||
98
test/variant_eq_ne_cx.cpp
Normal file
98
test/variant_eq_ne_cx.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
|
||||
// Copyright 2017, 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
using namespace boost::variant2;
|
||||
|
||||
#if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping constexpr op==, op!= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined")
|
||||
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
inline constexpr bool operator==( X const&, X const& ) { return false; }
|
||||
inline constexpr bool operator!=( X const&, X const& ) { return false; }
|
||||
|
||||
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
constexpr variant<int> v1, v2, v3( 1 ), v4( 1 );
|
||||
|
||||
STATIC_ASSERT( v1 == v2 );
|
||||
STATIC_ASSERT( !(v1 != v2) );
|
||||
|
||||
STATIC_ASSERT( v1 != v3 );
|
||||
STATIC_ASSERT( !(v1 == v3) );
|
||||
|
||||
STATIC_ASSERT( v3 == v4 );
|
||||
STATIC_ASSERT( !(v3 != v4) );
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f );
|
||||
|
||||
STATIC_ASSERT( v1 == v2 );
|
||||
STATIC_ASSERT( !(v1 != v2) );
|
||||
|
||||
STATIC_ASSERT( v1 != v3 );
|
||||
STATIC_ASSERT( !(v1 == v3) );
|
||||
|
||||
STATIC_ASSERT( v3 == v4 );
|
||||
STATIC_ASSERT( !(v3 != v4) );
|
||||
|
||||
STATIC_ASSERT( v1 != v5 );
|
||||
STATIC_ASSERT( !(v1 == v5) );
|
||||
|
||||
STATIC_ASSERT( v3 != v5 );
|
||||
STATIC_ASSERT( !(v3 == v5) );
|
||||
|
||||
STATIC_ASSERT( v5 == v6 );
|
||||
STATIC_ASSERT( !(v5 != v6) );
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f );
|
||||
|
||||
STATIC_ASSERT( v1 == v2 );
|
||||
STATIC_ASSERT( !(v1 != v2) );
|
||||
|
||||
STATIC_ASSERT( v1 != v3 );
|
||||
STATIC_ASSERT( !(v1 == v3) );
|
||||
|
||||
STATIC_ASSERT( v3 == v4 );
|
||||
STATIC_ASSERT( !(v3 != v4) );
|
||||
|
||||
STATIC_ASSERT( v1 != v5 );
|
||||
STATIC_ASSERT( !(v1 == v5) );
|
||||
|
||||
STATIC_ASSERT( v3 != v5 );
|
||||
STATIC_ASSERT( !(v3 == v5) );
|
||||
|
||||
STATIC_ASSERT( v5 == v6 );
|
||||
STATIC_ASSERT( !(v5 != v6) );
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<X> v1, v2;
|
||||
|
||||
STATIC_ASSERT( !(v1 == v2) );
|
||||
STATIC_ASSERT( !(v1 != v2) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
91
test/variant_lt_gt_cx.cpp
Normal file
91
test/variant_lt_gt_cx.cpp
Normal file
@@ -0,0 +1,91 @@
|
||||
|
||||
// Copyright 2017, 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
using namespace boost::variant2;
|
||||
|
||||
#if !defined(BOOST_MP11_HAS_CXX14_CONSTEXPR)
|
||||
|
||||
#include <boost/config/pragma_message.hpp>
|
||||
|
||||
BOOST_PRAGMA_MESSAGE("Skipping constexpr op<, op<= test because BOOST_MP11_HAS_CXX14_CONSTEXPR is not defined")
|
||||
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
struct X
|
||||
{
|
||||
};
|
||||
|
||||
inline constexpr bool operator<( X const&, X const& ) { return false; }
|
||||
inline constexpr bool operator>( X const&, X const& ) { return false; }
|
||||
inline constexpr bool operator<=( X const&, X const& ) { return false; }
|
||||
inline constexpr bool operator>=( X const&, X const& ) { return false; }
|
||||
|
||||
#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)
|
||||
|
||||
#define TEST_EQ( v1, v2 ) \
|
||||
STATIC_ASSERT( !(v1 < v2) ); \
|
||||
STATIC_ASSERT( !(v1 > v2) ); \
|
||||
STATIC_ASSERT( v1 <= v2 ); \
|
||||
STATIC_ASSERT( v1 >= v2 );
|
||||
|
||||
#define TEST_LE( v1, v3 ) \
|
||||
STATIC_ASSERT( v1 < v3 ); \
|
||||
STATIC_ASSERT( v3 > v1 ); \
|
||||
STATIC_ASSERT( !(v1 > v3) ); \
|
||||
STATIC_ASSERT( !(v3 < v1) ); \
|
||||
STATIC_ASSERT( v1 <= v3 ); \
|
||||
STATIC_ASSERT( v3 >= v1 ); \
|
||||
STATIC_ASSERT( !(v1 >= v3) ); \
|
||||
STATIC_ASSERT( !(v3 <= v1) );
|
||||
|
||||
int main()
|
||||
{
|
||||
{
|
||||
constexpr variant<int> v1, v2, v3( 1 ), v4( 1 );
|
||||
|
||||
TEST_EQ( v1, v2 )
|
||||
TEST_LE( v1, v3 )
|
||||
TEST_EQ( v3, v4 )
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<int, float> v1, v2, v3( 1 ), v4( 1 ), v5( 3.14f ), v6( 3.14f );
|
||||
|
||||
TEST_EQ( v1, v2 )
|
||||
TEST_LE( v1, v3 )
|
||||
TEST_EQ( v3, v4 )
|
||||
TEST_LE( v1, v5 )
|
||||
TEST_LE( v3, v5 )
|
||||
TEST_EQ( v5, v6 )
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<int, int, float> v1, v2, v3( in_place_index_t<1>{} ), v4( in_place_index_t<1>{} ), v5( 3.14f ), v6( 3.14f );
|
||||
|
||||
TEST_EQ( v1, v2 )
|
||||
TEST_LE( v1, v3 )
|
||||
TEST_EQ( v3, v4 )
|
||||
TEST_LE( v1, v5 )
|
||||
TEST_LE( v3, v5 )
|
||||
TEST_EQ( v5, v6 )
|
||||
}
|
||||
|
||||
{
|
||||
constexpr variant<X> v1, v2;
|
||||
|
||||
STATIC_ASSERT( !(v1 < v2) );
|
||||
STATIC_ASSERT( !(v1 > v2) );
|
||||
STATIC_ASSERT( !(v1 <= v2) );
|
||||
STATIC_ASSERT( !(v1 >= v2) );
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
51
test/variant_move_assign_throw.cpp
Normal file
51
test/variant_move_assign_throw.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct Y1
|
||||
{
|
||||
Y1() noexcept {} // =default fails on msvc-14.0
|
||||
|
||||
Y1(Y1&&)
|
||||
{
|
||||
throw std::runtime_error( "Y1(Y1&&)" );
|
||||
}
|
||||
|
||||
Y1& operator=(Y1&&) = default;
|
||||
};
|
||||
|
||||
struct Y2
|
||||
{
|
||||
Y2() noexcept {}
|
||||
|
||||
Y2(Y2&&)
|
||||
{
|
||||
throw std::runtime_error( "Y2(Y2&&)" );
|
||||
}
|
||||
|
||||
Y2& operator=(Y2&&) = default;
|
||||
};
|
||||
|
||||
void test()
|
||||
{
|
||||
variant<Y1, Y2> v1( in_place_type_t<Y1>{} );
|
||||
variant<Y1, Y2> v2( in_place_type_t<Y2>{} );
|
||||
|
||||
BOOST_TEST_THROWS( v1 = std::move( v2 ), std::runtime_error )
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -69,6 +69,16 @@ int main()
|
||||
test( variant<int, float>(1) );
|
||||
test( variant<int, float>(3.14f) );
|
||||
|
||||
test( variant<int const, float const>() );
|
||||
test( variant<int const, float const>(1) );
|
||||
test( variant<int const, float const>(3.14f) );
|
||||
|
||||
test( variant<std::string>() );
|
||||
test( variant<std::string>("test") );
|
||||
|
||||
test( variant<std::string const>() );
|
||||
test( variant<std::string const>("test") );
|
||||
|
||||
test( variant<int, float, std::string>() );
|
||||
test( variant<int, float, std::string>(1) );
|
||||
test( variant<int, float, std::string>(3.14f) );
|
||||
@@ -85,6 +95,8 @@ int main()
|
||||
|
||||
test( variant<std::string, std::string, float>() );
|
||||
|
||||
test( variant<X1 const>() );
|
||||
|
||||
test( variant<X1, X2>() );
|
||||
test( variant<X1, X2, int>() );
|
||||
test( variant<X1, X2, X2>() );
|
||||
|
||||
@@ -6,13 +6,6 @@
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if !defined( __cpp_constexpr ) || __cpp_constexpr < 201603
|
||||
|
||||
// no constexpr lambda support
|
||||
int main() {}
|
||||
|
||||
#else
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <utility>
|
||||
|
||||
@@ -44,7 +37,7 @@ enum E
|
||||
template<class T, class V> constexpr T test( V&& v )
|
||||
{
|
||||
V v2( std::forward<V>(v) );
|
||||
return get<T>(v);
|
||||
return get<T>( v2 );
|
||||
}
|
||||
|
||||
int main()
|
||||
@@ -109,5 +102,3 @@ int main()
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // constexpr lambda support
|
||||
|
||||
65
test/variant_move_construct_throw.cpp
Normal file
65
test/variant_move_construct_throw.cpp
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
// Copyright 2019 Peter Dimov
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <stdexcept>
|
||||
|
||||
using namespace boost::variant2;
|
||||
|
||||
struct X
|
||||
{
|
||||
static int instances;
|
||||
|
||||
X()
|
||||
{
|
||||
++instances;
|
||||
}
|
||||
|
||||
X( X const& )
|
||||
{
|
||||
throw std::runtime_error( "X(X const&)" );
|
||||
}
|
||||
|
||||
~X()
|
||||
{
|
||||
--instances;
|
||||
}
|
||||
};
|
||||
|
||||
int X::instances = 0;
|
||||
|
||||
void test()
|
||||
{
|
||||
X::instances = 0;
|
||||
|
||||
{
|
||||
variant<X> v1;
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
|
||||
try
|
||||
{
|
||||
variant<X> v2( std::move( v1 ) );
|
||||
BOOST_TEST_EQ( X::instances, 2 );
|
||||
}
|
||||
catch( std::exception const& )
|
||||
{
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 1 );
|
||||
}
|
||||
|
||||
BOOST_TEST_EQ( X::instances, 0 );
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test();
|
||||
return boost::report_errors();
|
||||
}
|
||||
@@ -25,40 +25,80 @@ int main()
|
||||
BOOST_TEST_EQ( (variant_size<variant<> volatile>::value), 0 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<> const volatile>::value), 0 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<>&>::value), 0 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<> const&>::value), 0 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<>&&>::value), 0 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<> const&&>::value), 0 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void>>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void> const>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void> volatile>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void> const volatile>::value), 1 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void>&>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void> const&>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void>&&>::value), 1 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void> const&&>::value), 1 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void>>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void> const>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void> volatile>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void> const volatile>::value), 2 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void>&>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void> const&>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void>&&>::value), 2 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void> const&&>::value), 2 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void>>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void> const>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void> volatile>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void> const volatile>::value), 3 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void>&>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void> const&>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void>&&>::value), 3 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void> const&&>::value), 3 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> volatile>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const volatile>::value), 4 );
|
||||
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>&>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const&>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void>&&>::value), 4 );
|
||||
BOOST_TEST_EQ( (variant_size<variant<void, void, void, void> const&&>::value), 4 );
|
||||
|
||||
variant_size<void>();
|
||||
variant_size<void const>();
|
||||
variant_size<void volatile>();
|
||||
variant_size<void const volatile>();
|
||||
|
||||
variant_size<int&>();
|
||||
variant_size<int const&>();
|
||||
variant_size<int&&>();
|
||||
variant_size<int const&&>();
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void const>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void volatile>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, void const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int const&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int&&>));
|
||||
BOOST_TEST_TRAIT_FALSE((mp_valid<var_size_t, int const&&>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> volatile>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const volatile>));
|
||||
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<>&&>));
|
||||
BOOST_TEST_TRAIT_TRUE((mp_valid<var_size_t, variant<> const&&>));
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user