• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Peter Dimov
2 //
3 // Distributed under the Boost Software License, Version 1.0.
4 //
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 
8 #if defined(ONLY_V2)
9 # define NO_BV
10 # define NO_SV
11 #endif
12 
13 #if defined(ONLY_BV)
14 # define NO_V2
15 # define NO_SV
16 #endif
17 
18 #if defined(ONLY_SV)
19 # define NO_V2
20 # define NO_BV
21 #endif
22 
23 #if !defined(NO_V2)
24 #include <boost/variant2/variant.hpp>
25 #endif
26 
27 #if !defined(NO_BV)
28 #include <boost/variant.hpp>
29 #endif
30 
31 #if !defined(NO_SV)
32 #include <variant>
33 #endif
34 
35 #include <type_traits>
36 #include <chrono>
37 #include <iostream>
38 #include <iomanip>
39 #include <vector>
40 #include <map>
41 #include <string>
42 #include <stdexcept>
43 
44 template<class T> struct is_numeric: std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value>
45 {
46 };
47 
48 template<class T, class U> struct have_addition: std::integral_constant<bool, is_numeric<T>::value && is_numeric<U>::value>
49 {
50 };
51 
add(T const & t,U const & u)52 template<class T, class U, class E = std::enable_if_t<have_addition<T, U>::value>> auto add( T const& t, U const& u )
53 {
54     return t + u;
55 }
56 
add(T const &,U const &)57 template<class T, class U, class E = std::enable_if_t<!have_addition<T, U>::value>> double add( T const& /*t*/, U const& /*u*/ )
58 {
59     throw std::logic_error( "Invalid addition" );
60 }
61 
to_double(double const & v)62 inline double to_double( double const& v )
63 {
64     return v;
65 }
66 
67 #if !defined(NO_V2)
68 
operator +(boost::variant2::variant<T...> const & v1,boost::variant2::variant<T...> const & v2)69 template<class... T> boost::variant2::variant<T...> operator+( boost::variant2::variant<T...> const& v1, boost::variant2::variant<T...> const& v2 )
70 {
71     return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant<T...> { return add( x1, x2 ); }, v1, v2 );
72 }
73 
to_double(boost::variant2::variant<T...> const & v)74 template<class... T> double to_double( boost::variant2::variant<T...> const& v )
75 {
76     return boost::variant2::get<double>( v );
77 }
78 
79 #endif
80 
81 #if !defined(NO_BV)
82 
operator +(boost::variant<T...> const & v1,boost::variant<T...> const & v2)83 template<class... T> boost::variant<T...> operator+( boost::variant<T...> const& v1, boost::variant<T...> const& v2 )
84 {
85     return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant<T...> { return add( x1, x2 ); }, v1, v2 );
86 }
87 
to_double(boost::variant<T...> const & v)88 template<class... T> double to_double( boost::variant<T...> const& v )
89 {
90     return boost::get<double>( v );
91 }
92 
93 #endif
94 
95 #if !defined(NO_SV)
96 
operator +(std::variant<T...> const & v1,std::variant<T...> const & v2)97 template<class... T> std::variant<T...> operator+( std::variant<T...> const& v1, std::variant<T...> const& v2 )
98 {
99     return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant<T...> { return add( x1, x2 ); }, v1, v2 );
100 }
101 
to_double(std::variant<T...> const & v)102 template<class... T> double to_double( std::variant<T...> const& v )
103 {
104     return std::get<double>( v );
105 }
106 
107 #endif
108 
test_(long long N)109 template<class V> void test_( long long N )
110 {
111     std::vector<V> w;
112     // lack of reserve is deliberate
113 
114     auto tp1 = std::chrono::high_resolution_clock::now();
115 
116     for( long long i = 0; i < N; ++i )
117     {
118         V v;
119 
120         if( i % 7 == 0 )
121         {
122             v = i / 7;
123         }
124         else
125         {
126             v = i / 7.0;
127         }
128 
129         w.push_back( v );
130     }
131 
132     V s = 0.0;
133 
134     for( long long i = 0; i < N; ++i )
135     {
136         s = s + w[ i ];
137     }
138 
139     auto tp2 = std::chrono::high_resolution_clock::now();
140 
141     std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n";
142 }
143 
test(long long N)144 template<class... T> void test( long long N )
145 {
146     std::cout << "N=" << N << ":\n";
147 
148     std::cout << "        double: "; test_<double>( N );
149 #if !defined(NO_V2)
150     std::cout << "      variant2: "; test_<boost::variant2::variant<T...>>( N );
151 #endif
152 #if !defined(NO_BV)
153     std::cout << "boost::variant: "; test_<boost::variant<T...>>( N );
154 #endif
155 #if !defined(NO_SV)
156     std::cout << "  std::variant: "; test_<std::variant<T...>>( N );
157 #endif
158 
159     std::cout << '\n';
160 }
161 
main()162 int main()
163 {
164     long long const N = 100'000'000LL;
165 
166     test<long long, double>( N );
167     test<std::nullptr_t, long long, double, std::string, std::vector<std::string>, std::map<std::string, std::string>>( N );
168 }
169