// 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 #endif #if !defined(NO_BV) #include #endif #if !defined(NO_SV) #include #endif #include #include #include #include #include #include #include #include template struct is_numeric: std::integral_constant::value || std::is_floating_point::value> { }; template struct have_addition: std::integral_constant::value && is_numeric::value> { }; template::value>> auto add( T const& t, U const& u ) { return t + u; } template::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 boost::variant2::variant operator+( boost::variant2::variant const& v1, boost::variant2::variant const& v2 ) { return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant { return add( x1, x2 ); }, v1, v2 ); } template double to_double( boost::variant2::variant const& v ) { return boost::variant2::get( v ); } #endif #if !defined(NO_BV) template boost::variant operator+( boost::variant const& v1, boost::variant const& v2 ) { return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant { return add( x1, x2 ); }, v1, v2 ); } template double to_double( boost::variant const& v ) { return boost::get( v ); } #endif #if !defined(NO_SV) template std::variant operator+( std::variant const& v1, std::variant const& v2 ) { return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant { return add( x1, x2 ); }, v1, v2 ); } template double to_double( std::variant const& v ) { return std::get( v ); } #endif template void test_( long long N ) { std::vector 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( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n"; } template void test( long long N ) { std::cout << "N=" << N << ":\n"; std::cout << " double: "; test_( N ); #if !defined(NO_V2) std::cout << " variant2: "; test_>( N ); #endif #if !defined(NO_BV) std::cout << "boost::variant: "; test_>( N ); #endif #if !defined(NO_SV) std::cout << " std::variant: "; test_>( N ); #endif std::cout << '\n'; } int main() { long long const N = 100'000'000LL; test( N ); test, std::map>( N ); }