Compare commits

..

33 Commits

Author SHA1 Message Date
Peter Dimov
1e986047ae Merge pull request #6 from akrzemi1/patch-1
docs: sizeof(T...) -> sizeof...(T)
2019-03-06 19:09:31 +02:00
Andrzej Krzemieński
107a43d5a0 docs: sizeof(T...) -> sizeof...(T) 2019-03-06 16:07:56 +01:00
Peter Dimov
1c3526b3bb Add test/variant_lt_gt_cx 2019-03-06 01:09:40 +02:00
Peter Dimov
204bcce9df Make relational operators constexpr; add test/variant_eq_ne_cx.cpp 2019-03-06 00:26:55 +02:00
Peter Dimov
e5e09c1c04 Only use mp_invoke_q on mp11 1.70 and above 2019-03-05 01:14:09 +02:00
Peter Dimov
2f589c7814 Make default constructors of some test types noexcept 2019-03-03 15:22:22 +02:00
Peter Dimov
fdfe9df167 Do not trivially copy/move assign when not trivially copy/move constructible 2019-03-03 05:14:51 +02:00
Peter Dimov
30d974d0fc Fix exception safety issue in copy/move/converting constructor 2019-02-26 15:12:37 +02:00
Peter Dimov
9d7a44761b Add more copy/move tests 2019-02-26 15:11:21 +02:00
Peter Dimov
2f376da1c2 Add throwing copy/move/convert tests 2019-02-26 14:26:59 +02:00
Peter Dimov
f05837061a Add benchmark2.md 2019-02-25 19:42:31 +02:00
Peter Dimov
3d946ecb71 Add benchmark2.cpp 2019-02-25 18:59:49 +02:00
Peter Dimov
8756a07f9a Add clang results 2019-02-25 02:48:08 +02:00
Peter Dimov
48c8145b4d Add benchmark1.cpp 2019-02-25 02:17:10 +02:00
Peter Dimov
8bbd6f238a Fix godbolt link in README 2019-02-22 22:04:33 +02:00
Peter Dimov
1b62998c96 Add index.html 2019-02-22 19:21:04 +02:00
Peter Dimov
8a7cc12716 Add html/ 2019-02-22 19:19:36 +02:00
Peter Dimov
b97a92c963 Rename to variant2 2019-02-22 19:19:03 +02:00
Peter Dimov
ea2e8d2cf6 Remove html/ from .gitignore 2019-02-22 19:10:48 +02:00
Peter Dimov
2ea2ff915b Fix documentation of get_if 2019-02-22 12:27:53 +02:00
Peter Dimov
d6d1cbd9fe Merge branch 'feature/more-travis' into feature/unsafe-get 2019-02-22 03:41:06 +02:00
Peter Dimov
f4d852e5ab Define detail::unsafe_get, use it in visit 2019-02-22 03:21:56 +02:00
Peter Dimov
89c58a9b83 Add clang 7 to Travis, test c++2a 2019-02-22 02:58:33 +02:00
Peter Dimov
831231a8b3 Merge branch 'feature/copy_cv_ref' into develop 2019-02-22 02:46:02 +02:00
Peter Dimov
4c8b0d2dee Document reference specializations of variant_size, variant_alternative 2019-02-22 02:07:47 +02:00
Peter Dimov
a0b499bc3b Use copy_cv_ref in apply_cv_ref instead of variant_alternative_t 2019-02-22 01:57:09 +02:00
Peter Dimov
c1287f9e95 Fix variant_alternative for g++ 4.8 2019-02-21 23:06:24 +02:00
Peter Dimov
34933c35bd Use variant_alternative_t directly for references 2019-02-21 22:42:21 +02:00
Peter Dimov
d8cd270268 Add reference specializations to variant_alternative 2019-02-21 22:22:07 +02:00
Peter Dimov
87a2e88edb Use variant_size directly with references 2019-02-21 22:03:56 +02:00
Peter Dimov
cf3ea64b45 Add reference specializations to variant_size 2019-02-21 21:57:39 +02:00
Peter Dimov
f67a6bd2ae Remove variant2:: qualifications, detail is no longer ambiguous 2019-02-21 21:40:06 +02:00
Peter Dimov
f3e101a841 Remove using namespace boost::mp11 2019-02-21 20:37:20 +02:00
28 changed files with 4080 additions and 276 deletions

View File

@@ -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:

View File

@@ -14,7 +14,7 @@ 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/6LSV3Z).
[standalone](https://godbolt.org/z/CTZztA).
Supported compilers:

168
benchmark/benchmark1.cpp Normal file
View 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
View 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
View 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
View 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
View File

@@ -1,2 +1 @@
/html/
/pdf/

View File

@@ -6,14 +6,14 @@
import asciidoctor ;
html variant.html : variant.adoc ;
html variant2.html : variant2.adoc ;
install html_ : variant.html : <location>html ;
install html_ : variant2.html : <location>html ;
pdf variant.pdf : variant.adoc ;
explicit variant.pdf ;
pdf variant2.pdf : variant2.adoc ;
explicit variant2.pdf ;
install pdf_ : variant.pdf : <location>pdf ;
install pdf_ : variant2.pdf : <location>pdf ;
explicit pdf_ ;
###############################################################################

2153
doc/html/variant2.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -16,8 +16,8 @@ Peter Dimov
:leveloffset: +1
include::variant/overview.adoc[]
include::variant/reference.adoc[]
include::variant/copyright.adoc[]
include::variant2/overview.adoc[]
include::variant2/reference.adoc[]
include::variant2/copyright.adoc[]
:leveloffset: -1

View File

@@ -41,6 +41,9 @@ 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;
@@ -56,6 +59,9 @@ 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;
@@ -103,11 +109,12 @@ template<size_t I, class... T>
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 T, class... T>
constexpr add_pointer_t<T>
template<class U, class... T>
constexpr add_pointer_t<U>
get_if(variant<T...>* v) noexcept;
template<class T, class... T>
constexpr add_pointer_t<const T>
template<class U, class... T>
constexpr add_pointer_t<const U>
get_if(const variant<T...>* v) noexcept;
// relational operators
@@ -489,7 +496,7 @@ template<size_t I, class... A>
[none]
* {blank}
+
Requires: :: `I < sizeof(T...)`.
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)...)`.
@@ -507,7 +514,7 @@ template<size_t I, class V, class... A>
[none]
* {blank}
+
Requires: :: `I < sizeof(T...)`.
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)...)`.
@@ -630,6 +637,12 @@ 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}
+
@@ -639,8 +652,10 @@ 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, the three structs have no `type` member.
Otherwise, these structs have no member `type`.
--
```
@@ -651,7 +666,7 @@ template<size_t I, class... T>
* {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 `type` member.
(zero-based) type in `T...`. Otherwise, there is no member `type`.
### holds_alternative
@@ -731,16 +746,6 @@ 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 T, class... T>
constexpr add_pointer_t<T>
get_if(variant<T...>* v) noexcept;
```
```
template<class T, class... T>
constexpr add_pointer_t<const T>
get_if(const variant<T...>* v) noexcept;
```
[none]
* {blank}
+
@@ -748,6 +753,24 @@ 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
```

File diff suppressed because it is too large Load Diff

15
index.html Normal file
View 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
-->

View File

@@ -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 ;

View File

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

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

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

View File

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

View 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
View 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
View 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

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

View File

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

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

View File

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