mirror of
https://github.com/boostorg/variant2.git
synced 2025-12-24 15:48:12 +01:00
Compare commits
27 Commits
feature/mo
...
feature/wa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1da3892239 | ||
|
|
3808c9b122 | ||
|
|
f1b1e7cade | ||
|
|
9875cfdc98 | ||
|
|
688849f9e8 | ||
|
|
1e986047ae | ||
|
|
107a43d5a0 | ||
|
|
1c3526b3bb | ||
|
|
204bcce9df | ||
|
|
e5e09c1c04 | ||
|
|
2f589c7814 | ||
|
|
fdfe9df167 | ||
|
|
30d974d0fc | ||
|
|
9d7a44761b | ||
|
|
2f376da1c2 | ||
|
|
f05837061a | ||
|
|
3d946ecb71 | ||
|
|
8756a07f9a | ||
|
|
48c8145b4d | ||
|
|
8bbd6f238a | ||
|
|
1b62998c96 | ||
|
|
8a7cc12716 | ||
|
|
b97a92c963 | ||
|
|
ea2e8d2cf6 | ||
|
|
2ea2ff915b | ||
|
|
d6d1cbd9fe | ||
|
|
f4d852e5ab |
@@ -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
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
1
doc/.gitignore
vendored
@@ -1,2 +1 @@
|
||||
/html/
|
||||
/pdf/
|
||||
|
||||
10
doc/Jamfile
10
doc/Jamfile
@@ -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
2153
doc/html/variant2.html
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -109,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
|
||||
@@ -495,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)...)`.
|
||||
@@ -513,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)...)`.
|
||||
@@ -745,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}
|
||||
+
|
||||
@@ -762,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
|
||||
|
||||
```
|
||||
@@ -1,259 +0,0 @@
|
||||
#ifndef BOOST_VARIANT2_OUTCOME_HPP_INCLUDED
|
||||
#define BOOST_VARIANT2_OUTCOME_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017 Peter Dimov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#endif
|
||||
#include <system_error>
|
||||
#include <exception>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace variant2
|
||||
{
|
||||
|
||||
enum class outcome_errc
|
||||
{
|
||||
not_initialized
|
||||
};
|
||||
|
||||
class outcome_error_category: public std::error_category
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char * name() const noexcept
|
||||
{
|
||||
return "boost::variant2::outcome";
|
||||
}
|
||||
|
||||
virtual std::string message( int e ) const
|
||||
{
|
||||
switch( e )
|
||||
{
|
||||
case (int)outcome_errc::not_initialized:
|
||||
|
||||
return "outcome<> not initialized";
|
||||
|
||||
default:
|
||||
|
||||
return "unknown outcome<> error";
|
||||
}
|
||||
}
|
||||
|
||||
static outcome_error_category const & instance()
|
||||
{
|
||||
static outcome_error_category cat;
|
||||
return cat;
|
||||
}
|
||||
};
|
||||
|
||||
std::error_code make_error_code( outcome_errc e )
|
||||
{
|
||||
return std::error_code( static_cast<int>( e ), outcome_error_category::instance() );
|
||||
}
|
||||
|
||||
template<class T> class outcome
|
||||
{
|
||||
private:
|
||||
|
||||
variant<T, std::error_code, std::exception_ptr> v_;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
constexpr outcome() noexcept: v_( make_error_code( outcome_errc::not_initialized ) )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr outcome( T const& t ): v_( t )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr outcome( T&& t ): v_( std::move(t) )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr outcome( std::error_code const & ec ) noexcept: v_( ec )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr outcome( std::exception_ptr const & ep ) noexcept: v_( ep )
|
||||
{
|
||||
}
|
||||
|
||||
// queries
|
||||
|
||||
constexpr bool has_value() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
constexpr bool has_error() const noexcept
|
||||
{
|
||||
return v_.index() == 1;
|
||||
}
|
||||
|
||||
constexpr bool has_exception() const noexcept
|
||||
{
|
||||
return v_.index() == 2;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
// checked value access
|
||||
|
||||
constexpr T& value() &
|
||||
{
|
||||
if( has_value() )
|
||||
{
|
||||
return *get_if<0>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::system_error( *get_if<1>(&v_) );
|
||||
}
|
||||
}
|
||||
|
||||
constexpr T const& value() const&
|
||||
{
|
||||
if( has_value() )
|
||||
{
|
||||
return *get_if<0>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::system_error( *get_if<1>(&v_) );
|
||||
}
|
||||
}
|
||||
|
||||
constexpr T&& value() &&
|
||||
{
|
||||
return std::move( value() );
|
||||
}
|
||||
|
||||
constexpr T const&& value() const&&
|
||||
{
|
||||
return std::move( value() );
|
||||
}
|
||||
|
||||
// unchecked value access
|
||||
|
||||
T* operator->() noexcept
|
||||
{
|
||||
return get_if<0>(&v_);
|
||||
}
|
||||
|
||||
T const* operator->() const noexcept
|
||||
{
|
||||
return get_if<0>(&v_);
|
||||
}
|
||||
|
||||
T& operator*() & noexcept
|
||||
{
|
||||
T* p = get_if<0>(&v_);
|
||||
|
||||
assert( p != 0 );
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
T const& operator*() const & noexcept
|
||||
{
|
||||
T const* p = get_if<0>(&v_);
|
||||
|
||||
assert( p != 0 );
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
T&& operator*() && noexcept
|
||||
{
|
||||
return std::move(**this);
|
||||
}
|
||||
|
||||
T const&& operator*() const && noexcept
|
||||
{
|
||||
return std::move(**this);
|
||||
}
|
||||
|
||||
// error access
|
||||
|
||||
/*constexpr*/ std::error_code error() const noexcept
|
||||
{
|
||||
if( has_error() )
|
||||
{
|
||||
return *get_if<1>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
|
||||
// exception access
|
||||
|
||||
std::exception_ptr exception() const noexcept
|
||||
{
|
||||
if( has_exception() )
|
||||
{
|
||||
return *get_if<2>(&v_);
|
||||
}
|
||||
else if( has_value() )
|
||||
{
|
||||
return std::exception_ptr();
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::make_exception_ptr( std::system_error( *get_if<1>(&v_) ) );
|
||||
}
|
||||
}
|
||||
|
||||
// setters
|
||||
|
||||
void set_value( T const& t ) noexcept( std::is_nothrow_copy_constructible<T>::value )
|
||||
{
|
||||
v_.emplace<0>( t );
|
||||
}
|
||||
|
||||
void set_value( T&& t ) noexcept( std::is_nothrow_move_constructible<T>::value )
|
||||
{
|
||||
v_.emplace<0>( std::move( t ) );
|
||||
}
|
||||
|
||||
void set_error( std::error_code const & e ) noexcept
|
||||
{
|
||||
v_.emplace<1>( e );
|
||||
}
|
||||
|
||||
void set_exception( std::exception_ptr const & x ) noexcept
|
||||
{
|
||||
v_.emplace<2>( x );
|
||||
}
|
||||
|
||||
// swap
|
||||
|
||||
void swap( outcome& r ) noexcept( noexcept( v_.swap( r.v_ ) ) )
|
||||
{
|
||||
v_.swap( r.v_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace variant2
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_VARIANT2_OUTCOME_HPP_INCLUDED
|
||||
@@ -1,226 +0,0 @@
|
||||
#ifndef BOOST_VARIANT2_RESULT_HPP_INCLUDED
|
||||
#define BOOST_VARIANT2_RESULT_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017 Peter Dimov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#endif
|
||||
#include <system_error>
|
||||
#include <type_traits>
|
||||
#include <cassert>
|
||||
|
||||
//
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace variant2
|
||||
{
|
||||
|
||||
enum class result_errc
|
||||
{
|
||||
not_initialized
|
||||
};
|
||||
|
||||
class result_error_category: public std::error_category
|
||||
{
|
||||
public:
|
||||
|
||||
virtual const char * name() const noexcept
|
||||
{
|
||||
return "boost::variant2::result";
|
||||
}
|
||||
|
||||
virtual std::string message( int e ) const
|
||||
{
|
||||
switch( e )
|
||||
{
|
||||
case (int)result_errc::not_initialized:
|
||||
|
||||
return "result<> not initialized";
|
||||
|
||||
default:
|
||||
|
||||
return "unknown result<> error";
|
||||
}
|
||||
}
|
||||
|
||||
static result_error_category const & instance()
|
||||
{
|
||||
static result_error_category cat;
|
||||
return cat;
|
||||
}
|
||||
};
|
||||
|
||||
std::error_code make_error_code( result_errc e )
|
||||
{
|
||||
return std::error_code( static_cast<int>( e ), result_error_category::instance() );
|
||||
}
|
||||
|
||||
template<class T> class result
|
||||
{
|
||||
private:
|
||||
|
||||
variant<T, std::error_code> v_;
|
||||
|
||||
public:
|
||||
|
||||
// constructors
|
||||
|
||||
constexpr result() noexcept: v_( make_error_code( result_errc::not_initialized ) )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr result( T const& t ): v_( t )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr result( T&& t ): v_( std::move(t) )
|
||||
{
|
||||
}
|
||||
|
||||
constexpr result( std::error_code const & ec ) noexcept: v_( ec )
|
||||
{
|
||||
}
|
||||
|
||||
// queries
|
||||
|
||||
constexpr bool has_value() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
constexpr bool has_error() const noexcept
|
||||
{
|
||||
return v_.index() == 1;
|
||||
}
|
||||
|
||||
constexpr explicit operator bool() const noexcept
|
||||
{
|
||||
return v_.index() == 0;
|
||||
}
|
||||
|
||||
// checked value access
|
||||
|
||||
constexpr T& value() &
|
||||
{
|
||||
if( has_value() )
|
||||
{
|
||||
return *get_if<0>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::system_error( *get_if<1>(&v_) );
|
||||
}
|
||||
}
|
||||
|
||||
constexpr T const& value() const&
|
||||
{
|
||||
if( has_value() )
|
||||
{
|
||||
return *get_if<0>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::system_error( *get_if<1>(&v_) );
|
||||
}
|
||||
}
|
||||
|
||||
constexpr T&& value() &&
|
||||
{
|
||||
return std::move( value() );
|
||||
}
|
||||
|
||||
constexpr T const&& value() const&&
|
||||
{
|
||||
return std::move( value() );
|
||||
}
|
||||
|
||||
// unchecked value access
|
||||
|
||||
T* operator->() noexcept
|
||||
{
|
||||
return get_if<0>(&v_);
|
||||
}
|
||||
|
||||
T const* operator->() const noexcept
|
||||
{
|
||||
return get_if<0>(&v_);
|
||||
}
|
||||
|
||||
T& operator*() & noexcept
|
||||
{
|
||||
T* p = get_if<0>(&v_);
|
||||
|
||||
assert( p != 0 );
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
T const& operator*() const & noexcept
|
||||
{
|
||||
T const* p = get_if<0>(&v_);
|
||||
|
||||
assert( p != 0 );
|
||||
|
||||
return *p;
|
||||
}
|
||||
|
||||
T&& operator*() && noexcept
|
||||
{
|
||||
return std::move(**this);
|
||||
}
|
||||
|
||||
T const&& operator*() const && noexcept
|
||||
{
|
||||
return std::move(**this);
|
||||
}
|
||||
|
||||
// error access
|
||||
|
||||
/*constexpr*/ std::error_code error() const noexcept
|
||||
{
|
||||
if( has_error() )
|
||||
{
|
||||
return *get_if<1>(&v_);
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
|
||||
// setters
|
||||
|
||||
void set_value( T const& t ) noexcept( std::is_nothrow_copy_constructible<T>::value )
|
||||
{
|
||||
v_.emplace<0>( t );
|
||||
}
|
||||
|
||||
void set_value( T&& t ) noexcept( std::is_nothrow_move_constructible<T>::value )
|
||||
{
|
||||
v_.emplace<0>( std::move( t ) );
|
||||
}
|
||||
|
||||
void set_error( std::error_code const & e ) noexcept
|
||||
{
|
||||
v_.emplace<1>( e );
|
||||
}
|
||||
|
||||
// swap
|
||||
|
||||
void swap( result& r ) noexcept( noexcept( v_.swap( r.v_ ) ) )
|
||||
{
|
||||
v_.swap( r.v_ );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace variant2
|
||||
} // namespace boost
|
||||
|
||||
#endif // #ifndef BOOST_VARIANT2_RESULT_HPP_INCLUDED
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef BOOST_VARIANT2_VARIANT_HPP_INCLUDED
|
||||
#define BOOST_VARIANT2_VARIANT_HPP_INCLUDED
|
||||
|
||||
// Copyright 2017, 2018 Peter Dimov.
|
||||
// Copyright 2017-2019 Peter Dimov.
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0.
|
||||
//
|
||||
@@ -224,8 +224,16 @@ template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#if defined( BOOST_MP11_VERSION ) && BOOST_MP11_VERSION >= 107000
|
||||
|
||||
template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke_q<Q, variant_alternative_t<I::value, T>>;
|
||||
|
||||
#else
|
||||
|
||||
template<class I, class T, class Q> using var_alt_impl = mp11::mp_invoke<Q, variant_alternative_t<I::value, T>>;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<std::size_t I, class T> struct variant_alternative
|
||||
@@ -258,6 +266,10 @@ template<std::size_t I, class... T> struct variant_alternative<I, variant<T...>>
|
||||
|
||||
#endif
|
||||
|
||||
// variant_npos
|
||||
|
||||
constexpr std::size_t variant_npos = ~static_cast<std::size_t>( 0 );
|
||||
|
||||
// holds_alternative
|
||||
|
||||
template<class U, class... T> constexpr bool holds_alternative( variant<T...> const& v ) noexcept
|
||||
@@ -312,6 +324,37 @@ template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T
|
||||
#endif
|
||||
}
|
||||
|
||||
// detail::unsafe_get (for visit)
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>& unsafe_get(variant<T...>& v)
|
||||
{
|
||||
static_assert( I < sizeof...(T), "Index out of bounds" );
|
||||
return v._get_impl( mp11::mp_size_t<I>() );
|
||||
}
|
||||
|
||||
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>>&& unsafe_get(variant<T...>&& v)
|
||||
{
|
||||
static_assert( I < sizeof...(T), "Index out of bounds" );
|
||||
return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
|
||||
}
|
||||
|
||||
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const& unsafe_get(variant<T...> const& v)
|
||||
{
|
||||
static_assert( I < sizeof...(T), "Index out of bounds" );
|
||||
return v._get_impl( mp11::mp_size_t<I>() );
|
||||
}
|
||||
|
||||
template<std::size_t I, class... T> constexpr variant_alternative_t<I, variant<T...>> const&& unsafe_get(variant<T...> const&& v)
|
||||
{
|
||||
static_assert( I < sizeof...(T), "Index out of bounds" );
|
||||
return std::move( v._get_impl( mp11::mp_size_t<I>() ) );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
// get (type)
|
||||
|
||||
template<class U, class... T> constexpr U& get(variant<T...>& v)
|
||||
@@ -577,6 +620,13 @@ template<class... T> struct variant_base_impl<true, true, T...>
|
||||
{
|
||||
}
|
||||
|
||||
// requires: ix_ == 0
|
||||
template<class I, class... A> void _replace( I, A&&... a )
|
||||
{
|
||||
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
|
||||
ix_ = I::value + 1;
|
||||
}
|
||||
|
||||
constexpr std::size_t index() const noexcept
|
||||
{
|
||||
return ix_ - 1;
|
||||
@@ -669,6 +719,13 @@ template<class... T> struct variant_base_impl<true, false, T...>
|
||||
{
|
||||
}
|
||||
|
||||
// requires: ix_ == 0
|
||||
template<class I, class... A> void _replace( I, A&&... a )
|
||||
{
|
||||
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
|
||||
ix_ = I::value + 1;
|
||||
}
|
||||
|
||||
constexpr std::size_t index() const noexcept
|
||||
{
|
||||
return ix_ >= 0? ix_ - 1: -ix_ - 1;
|
||||
@@ -724,6 +781,13 @@ template<class... T> struct variant_base_impl<false, true, T...>
|
||||
{
|
||||
}
|
||||
|
||||
// requires: ix_ == 0
|
||||
template<class I, class... A> void _replace( I, A&&... a )
|
||||
{
|
||||
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
|
||||
ix_ = I::value + 1;
|
||||
}
|
||||
|
||||
//[&]( auto I ){
|
||||
// using U = mp_at_c<mp_list<none, T...>, I>;
|
||||
// st1_.get( I ).~U();
|
||||
@@ -838,6 +902,13 @@ template<class... T> struct variant_base_impl<false, false, T...>
|
||||
{
|
||||
}
|
||||
|
||||
// requires: ix_ == 0
|
||||
template<class I, class... A> void _replace( I, A&&... a )
|
||||
{
|
||||
::new( &st1_ ) variant_storage<none, T...>( mp11::mp_size_t<I::value + 1>(), std::forward<A>(a)... );
|
||||
ix_ = I::value + 1;
|
||||
}
|
||||
|
||||
//[&]( auto I ){
|
||||
// using U = mp_at_c<mp_list<none, T...>, I>;
|
||||
// st1_.get( I ).~U();
|
||||
@@ -1059,7 +1130,7 @@ private:
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
::new( static_cast<void*>( this_ ) ) variant_base( i, r._get_impl( i ) );
|
||||
this_->_replace( i, r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1092,7 +1163,7 @@ private:
|
||||
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
::new( static_cast<void*>( this_ ) ) variant_base( i, std::move( r._get_impl( i ) ) );
|
||||
this_->_replace( i, std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1142,7 +1213,7 @@ public:
|
||||
|
||||
// assignment
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_assignable<T>...>, E1>
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r ) noexcept
|
||||
{
|
||||
@@ -1173,7 +1244,7 @@ private:
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_assignable<T>...>>, E1>,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_copy_constructible<T>..., detail::is_trivially_copy_assignable<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_copy_constructible<T>..., std::is_copy_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant const & r )
|
||||
@@ -1184,7 +1255,7 @@ public:
|
||||
}
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_assignable<T>...>, E1>
|
||||
class E2 = mp11::mp_if<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>, E1>
|
||||
>
|
||||
BOOST_CXX14_CONSTEXPR variant& operator=( variant && r ) noexcept
|
||||
{
|
||||
@@ -1215,7 +1286,7 @@ private:
|
||||
public:
|
||||
|
||||
template<class E1 = void,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_assignable<T>...>>, E1>,
|
||||
class E2 = mp11::mp_if<mp11::mp_not<mp11::mp_all<std::is_trivially_destructible<T>..., detail::is_trivially_move_constructible<T>..., detail::is_trivially_move_assignable<T>...>>, E1>,
|
||||
class E3 = mp11::mp_if<mp11::mp_all<std::is_move_constructible<T>..., std::is_move_assignable<T>...>, E1>
|
||||
>
|
||||
variant& operator=( variant && r )
|
||||
@@ -1283,6 +1354,11 @@ public:
|
||||
|
||||
// value status
|
||||
|
||||
constexpr bool valueless_by_exception() const noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using variant_base::index;
|
||||
|
||||
// swap
|
||||
@@ -1338,7 +1414,7 @@ private:
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
|
||||
::new( static_cast<void*>(this_) ) variant_base( J{}, r._get_impl( i ) );
|
||||
this_->_replace( J{}, r._get_impl( i ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1362,7 +1438,7 @@ private:
|
||||
template<class I> void operator()( I i ) const
|
||||
{
|
||||
using J = mp11::mp_find<mp11::mp_list<T...>, mp11::mp_at<mp11::mp_list<U...>, I>>;
|
||||
::new( static_cast<void*>(this_) ) variant_base( J{}, std::move( r._get_impl( i ) ) );
|
||||
this_->_replace( J{}, std::move( r._get_impl( i ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1495,7 +1571,7 @@ template<class... T> struct eq_L
|
||||
variant<T...> const & v;
|
||||
variant<T...> const & w;
|
||||
|
||||
template<class I> bool operator()( I i ) const
|
||||
template<class I> constexpr bool operator()( I i ) const
|
||||
{
|
||||
return v._get_impl( i ) == w._get_impl( i );
|
||||
}
|
||||
@@ -1516,7 +1592,7 @@ template<class... T> struct ne_L
|
||||
variant<T...> const & v;
|
||||
variant<T...> const & w;
|
||||
|
||||
template<class I> bool operator()( I i ) const
|
||||
template<class I> constexpr bool operator()( I i ) const
|
||||
{
|
||||
return v._get_impl( i ) != w._get_impl( i );
|
||||
}
|
||||
@@ -1537,7 +1613,7 @@ template<class... T> struct lt_L
|
||||
variant<T...> const & v;
|
||||
variant<T...> const & w;
|
||||
|
||||
template<class I> bool operator()( I i ) const
|
||||
template<class I> constexpr bool operator()( I i ) const
|
||||
{
|
||||
return v._get_impl( i ) < w._get_impl( i );
|
||||
}
|
||||
@@ -1563,7 +1639,7 @@ template<class... T> struct le_L
|
||||
variant<T...> const & v;
|
||||
variant<T...> const & w;
|
||||
|
||||
template<class I> bool operator()( I i ) const
|
||||
template<class I> constexpr bool operator()( I i ) const
|
||||
{
|
||||
return v._get_impl( i ) <= w._get_impl( i );
|
||||
}
|
||||
@@ -1589,32 +1665,32 @@ template<class T> using remove_cv_ref_t = typename std::remove_cv<typename std::
|
||||
|
||||
template<class T, class U> struct copy_cv_ref
|
||||
{
|
||||
using type = T;
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class T, class U> struct copy_cv_ref<T, U const>
|
||||
{
|
||||
using type = T const;
|
||||
using type = T const;
|
||||
};
|
||||
|
||||
template<class T, class U> struct copy_cv_ref<T, U volatile>
|
||||
{
|
||||
using type = T volatile;
|
||||
using type = T volatile;
|
||||
};
|
||||
|
||||
template<class T, class U> struct copy_cv_ref<T, U const volatile>
|
||||
{
|
||||
using type = T const volatile;
|
||||
using type = T const volatile;
|
||||
};
|
||||
|
||||
template<class T, class U> struct copy_cv_ref<T, U&>
|
||||
{
|
||||
using type = typename copy_cv_ref<T, U>::type&;
|
||||
using type = typename copy_cv_ref<T, U>::type&;
|
||||
};
|
||||
|
||||
template<class T, class U> struct copy_cv_ref<T, U&&>
|
||||
{
|
||||
using type = typename copy_cv_ref<T, U>::type&&;
|
||||
using type = typename copy_cv_ref<T, U>::type&&;
|
||||
};
|
||||
|
||||
template<class T, class U> using copy_cv_ref_t = typename copy_cv_ref<T, U>::type;
|
||||
@@ -1647,7 +1723,7 @@ template<class F, class V1> struct visit_L1
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1>
|
||||
{
|
||||
return std::forward<F>(f)( get<I::value>( std::forward<V1>(v1) ) );
|
||||
return std::forward<F>(f)( unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1688,7 +1764,7 @@ template<class F, class V1, class V2> struct visit_L2
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), get<I::value>( std::forward<V1>(v1) ) );
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2) );
|
||||
}
|
||||
};
|
||||
@@ -1713,7 +1789,7 @@ template<class F, class V1, class V2, class V3> struct visit_L3
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), get<I::value>( std::forward<V1>(v1) ) );
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3) );
|
||||
}
|
||||
};
|
||||
@@ -1739,7 +1815,7 @@ template<class F, class V1, class V2, class V3, class V4> struct visit_L4
|
||||
|
||||
template<class I> auto operator()( I ) const -> Vret<F, V1, V2, V3, V4>
|
||||
{
|
||||
auto f2 = bind_front( std::forward<F>(f), get<I::value>( std::forward<V1>(v1) ) );
|
||||
auto f2 = bind_front( std::forward<F>(f), unsafe_get<I::value>( std::forward<V1>(v1) ) );
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V3>(v3), std::forward<V4>(v4) );
|
||||
}
|
||||
};
|
||||
@@ -1757,7 +1833,7 @@ template<class F, class V1, class V2, class... V> constexpr auto visit( F&& f, V
|
||||
{
|
||||
return mp11::mp_with_index<variant_size<V1>>( v1.index(), [&]( auto I ){
|
||||
|
||||
auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
|
||||
auto f2 = [&]( auto&&... a ){ return std::forward<F>(f)( detail::unsafe_get<I.value>( std::forward<V1>(v1) ), std::forward<decltype(a)>(a)... ); };
|
||||
return visit( f2, std::forward<V2>(v2), std::forward<V>(v)... );
|
||||
|
||||
});
|
||||
|
||||
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
|
||||
-->
|
||||
31
test/Jamfile
31
test/Jamfile
@@ -1,6 +1,6 @@
|
||||
# Boost.Variant2 Library Test Jamfile
|
||||
#
|
||||
# Copyright 2015-2017 Peter Dimov
|
||||
# Copyright 2015-2019 Peter Dimov
|
||||
#
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -9,7 +9,19 @@
|
||||
import testing ;
|
||||
import ../../config/checks/config : requires ;
|
||||
|
||||
project : requirements [ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_constexpr ] ;
|
||||
project
|
||||
: default-build
|
||||
|
||||
<warnings>all
|
||||
|
||||
: requirements
|
||||
|
||||
[ requires cxx11_variadic_templates cxx11_template_aliases cxx11_decltype cxx11_constexpr ]
|
||||
|
||||
<toolset>msvc:<warnings-as-errors>on
|
||||
<toolset>gcc:<warnings-as-errors>on
|
||||
<toolset>clang:<warnings-as-errors>on
|
||||
;
|
||||
|
||||
run variant_size.cpp ;
|
||||
run variant_alternative.cpp ;
|
||||
@@ -57,10 +69,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 ;
|
||||
|
||||
95
test/variant_convert_construct_throw.cpp
Normal file
95
test/variant_convert_construct_throw.cpp
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
// 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(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#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();
|
||||
}
|
||||
55
test/variant_copy_assign_throw.cpp
Normal file
55
test/variant_copy_assign_throw.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// 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(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#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>() );
|
||||
|
||||
69
test/variant_copy_construct_throw.cpp
Normal file
69
test/variant_copy_construct_throw.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
// 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(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#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
|
||||
55
test/variant_move_assign_throw.cpp
Normal file
55
test/variant_move_assign_throw.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
|
||||
// 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(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#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>() );
|
||||
|
||||
69
test/variant_move_construct_throw.cpp
Normal file
69
test/variant_move_construct_throw.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
// 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(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#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();
|
||||
}
|
||||
@@ -6,6 +6,10 @@
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/core/lightweight_test_trait.hpp>
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning( disable: 4702 ) // unreachable code
|
||||
#endif
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
Reference in New Issue
Block a user