benchmark1.cpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. #if defined(ONLY_V2)
  8. # define NO_BV
  9. # define NO_SV
  10. #endif
  11. #if defined(ONLY_BV)
  12. # define NO_V2
  13. # define NO_SV
  14. #endif
  15. #if defined(ONLY_SV)
  16. # define NO_V2
  17. # define NO_BV
  18. #endif
  19. #if !defined(NO_V2)
  20. #include <boost/variant2/variant.hpp>
  21. #endif
  22. #if !defined(NO_BV)
  23. #include <boost/variant.hpp>
  24. #endif
  25. #if !defined(NO_SV)
  26. #include <variant>
  27. #endif
  28. #include <type_traits>
  29. #include <chrono>
  30. #include <iostream>
  31. #include <iomanip>
  32. #include <vector>
  33. #include <map>
  34. #include <string>
  35. #include <stdexcept>
  36. template<class T> struct is_numeric: std::integral_constant<bool, std::is_integral<T>::value || std::is_floating_point<T>::value>
  37. {
  38. };
  39. template<class T, class U> struct have_addition: std::integral_constant<bool, is_numeric<T>::value && is_numeric<U>::value>
  40. {
  41. };
  42. template<class T, class U, class E = std::enable_if_t<have_addition<T, U>::value>> auto add( T const& t, U const& u )
  43. {
  44. return t + u;
  45. }
  46. template<class T, class U, class E = std::enable_if_t<!have_addition<T, U>::value>> double add( T const& /*t*/, U const& /*u*/ )
  47. {
  48. throw std::logic_error( "Invalid addition" );
  49. }
  50. inline double to_double( double const& v )
  51. {
  52. return v;
  53. }
  54. #if !defined(NO_V2)
  55. template<class... T> boost::variant2::variant<T...> operator+( boost::variant2::variant<T...> const& v1, boost::variant2::variant<T...> const& v2 )
  56. {
  57. return visit( [&]( auto const& x1, auto const & x2 ) -> boost::variant2::variant<T...> { return add( x1, x2 ); }, v1, v2 );
  58. }
  59. template<class... T> double to_double( boost::variant2::variant<T...> const& v )
  60. {
  61. return boost::variant2::get<double>( v );
  62. }
  63. #endif
  64. #if !defined(NO_BV)
  65. template<class... T> boost::variant<T...> operator+( boost::variant<T...> const& v1, boost::variant<T...> const& v2 )
  66. {
  67. return boost::apply_visitor( [&]( auto const& x1, auto const & x2 ) -> boost::variant<T...> { return add( x1, x2 ); }, v1, v2 );
  68. }
  69. template<class... T> double to_double( boost::variant<T...> const& v )
  70. {
  71. return boost::get<double>( v );
  72. }
  73. #endif
  74. #if !defined(NO_SV)
  75. template<class... T> std::variant<T...> operator+( std::variant<T...> const& v1, std::variant<T...> const& v2 )
  76. {
  77. return visit( [&]( auto const& x1, auto const & x2 ) -> std::variant<T...> { return add( x1, x2 ); }, v1, v2 );
  78. }
  79. template<class... T> double to_double( std::variant<T...> const& v )
  80. {
  81. return std::get<double>( v );
  82. }
  83. #endif
  84. template<class V> void test_( long long N )
  85. {
  86. std::vector<V> w;
  87. // lack of reserve is deliberate
  88. auto tp1 = std::chrono::high_resolution_clock::now();
  89. for( long long i = 0; i < N; ++i )
  90. {
  91. V v;
  92. if( i % 7 == 0 )
  93. {
  94. v = i / 7;
  95. }
  96. else
  97. {
  98. v = i / 7.0;
  99. }
  100. w.push_back( v );
  101. }
  102. V s = 0.0;
  103. for( long long i = 0; i < N; ++i )
  104. {
  105. s = s + w[ i ];
  106. }
  107. auto tp2 = std::chrono::high_resolution_clock::now();
  108. std::cout << std::setw( 6 ) << std::chrono::duration_cast<std::chrono::milliseconds>( tp2 - tp1 ).count() << " ms; S=" << to_double( s ) << "\n";
  109. }
  110. template<class... T> void test( long long N )
  111. {
  112. std::cout << "N=" << N << ":\n";
  113. std::cout << " double: "; test_<double>( N );
  114. #if !defined(NO_V2)
  115. std::cout << " variant2: "; test_<boost::variant2::variant<T...>>( N );
  116. #endif
  117. #if !defined(NO_BV)
  118. std::cout << "boost::variant: "; test_<boost::variant<T...>>( N );
  119. #endif
  120. #if !defined(NO_SV)
  121. std::cout << " std::variant: "; test_<std::variant<T...>>( N );
  122. #endif
  123. std::cout << '\n';
  124. }
  125. int main()
  126. {
  127. long long const N = 100'000'000LL;
  128. test<long long, double>( N );
  129. test<std::nullptr_t, long long, double, std::string, std::vector<std::string>, std::map<std::string, std::string>>( N );
  130. }