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
41 struct prefix
42 {
43 int v_;
44 };
45
46 struct X1: prefix {};
47 struct X2: prefix {};
48 struct X3: prefix {};
49 struct X4: prefix {};
50 struct X5: prefix {};
51 struct X6: prefix {};
52 struct X7: prefix {};
53 struct X8: prefix {};
54 struct X9: prefix {};
55 struct X10: prefix {};
56 struct X11: prefix {};
57 struct X12: prefix {};
58
get_value(prefix const & v)59 inline int get_value( prefix const& v )
60 {
61 return v.v_;
62 }
63
64 #if !defined(NO_V2)
65
get_value(boost::variant2::variant<T...> const & v)66 template<class... T> int get_value( boost::variant2::variant<T...> const& v )
67 {
68 return visit( []( prefix const& x ) { return x.v_; }, v );
69 }
70
71 #endif
72
73 #if !defined(NO_BV)
74
get_value(boost::variant<T...> const & v)75 template<class... T> int get_value( boost::variant<T...> const& v )
76 {
77 return boost::apply_visitor( []( prefix const& x ) { return x.v_; }, v );
78 }
79
80 #endif
81
82 #if !defined(NO_SV)
83
get_value(std::variant<T...> const & v)84 template<class... T> int get_value( std::variant<T...> const& v )
85 {
86 return visit( []( prefix const& x ) { return x.v_; }, v );
87 }
88
89 #endif
90
test_(int N)91 template<class V> void test_( int N )
92 {
93 std::vector<V> w;
94 // lack of reserve is deliberate
95
96 auto tp1 = std::chrono::high_resolution_clock::now();
97
98 for( int i = 0; i < N / 12; ++i )
99 {
100 w.push_back( X1{ i } );
101 w.push_back( X2{ i } );
102 w.push_back( X3{ i } );
103 w.push_back( X4{ i } );
104 w.push_back( X5{ i } );
105 w.push_back( X6{ i } );
106 w.push_back( X7{ i } );
107 w.push_back( X8{ i } );
108 w.push_back( X9{ i } );
109 w.push_back( X10{ i } );
110 w.push_back( X11{ i } );
111 w.push_back( X12{ i } );
112 }
113
114 unsigned long long s = 0;
115
116 for( std::size_t i = 0, n = w.size(); i < n; ++i )
117 {
118 s = s + get_value( w[ i ] );
119 }
120
121 auto tp2 = std::chrono::high_resolution_clock::now();
122
123 std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << s << "\n";
124 }
125
test(int N)126 template<class... T> void test( int N )
127 {
128 std::cout << "N=" << N << ":\n";
129
130 std::cout << " prefix: "; test_<prefix>( N );
131 #if !defined(NO_V2)
132 std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N );
133 #endif
134 #if !defined(NO_BV)
135 std::cout << "boost::variant: "; test_<boost::variant<T...>>( N );
136 #endif
137 #if !defined(NO_SV)
138 std::cout << " std::variant: "; test_<std::variant<T...>>( N );
139 #endif
140
141 std::cout << '\n';
142 }
143
main()144 int main()
145 {
146 int const N = 100'000'000;
147
148 test<X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12>( N );
149 }
150