functional.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. // Copyright (c) 2016-2021 Antony Polukhin
  2. //
  3. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  4. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_PFR_DETAIL_FUNCTIONAL_HPP
  6. #define BOOST_PFR_DETAIL_FUNCTIONAL_HPP
  7. #pragma once
  8. #include <boost/pfr/detail/config.hpp>
  9. #include <functional>
  10. #include <boost/pfr/detail/sequence_tuple.hpp>
  11. namespace boost { namespace pfr { namespace detail {
  12. template <std::size_t I, std::size_t N>
  13. struct equal_impl {
  14. template <class T, class U>
  15. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  16. return ::boost::pfr::detail::sequence_tuple::get<I>(v1) == ::boost::pfr::detail::sequence_tuple::get<I>(v2)
  17. && equal_impl<I + 1, N>::cmp(v1, v2);
  18. }
  19. };
  20. template <std::size_t N>
  21. struct equal_impl<N, N> {
  22. template <class T, class U>
  23. constexpr static bool cmp(const T&, const U&) noexcept {
  24. return T::size_v == U::size_v;
  25. }
  26. };
  27. template <std::size_t I, std::size_t N>
  28. struct not_equal_impl {
  29. template <class T, class U>
  30. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  31. return ::boost::pfr::detail::sequence_tuple::get<I>(v1) != ::boost::pfr::detail::sequence_tuple::get<I>(v2)
  32. || not_equal_impl<I + 1, N>::cmp(v1, v2);
  33. }
  34. };
  35. template <std::size_t N>
  36. struct not_equal_impl<N, N> {
  37. template <class T, class U>
  38. constexpr static bool cmp(const T&, const U&) noexcept {
  39. return T::size_v != U::size_v;
  40. }
  41. };
  42. template <std::size_t I, std::size_t N>
  43. struct less_impl {
  44. template <class T, class U>
  45. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  46. return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
  47. || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_impl<I + 1, N>::cmp(v1, v2));
  48. }
  49. };
  50. template <std::size_t N>
  51. struct less_impl<N, N> {
  52. template <class T, class U>
  53. constexpr static bool cmp(const T&, const U&) noexcept {
  54. return T::size_v < U::size_v;
  55. }
  56. };
  57. template <std::size_t I, std::size_t N>
  58. struct less_equal_impl {
  59. template <class T, class U>
  60. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  61. return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
  62. || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_equal_impl<I + 1, N>::cmp(v1, v2));
  63. }
  64. };
  65. template <std::size_t N>
  66. struct less_equal_impl<N, N> {
  67. template <class T, class U>
  68. constexpr static bool cmp(const T&, const U&) noexcept {
  69. return T::size_v <= U::size_v;
  70. }
  71. };
  72. template <std::size_t I, std::size_t N>
  73. struct greater_impl {
  74. template <class T, class U>
  75. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  76. return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
  77. || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_impl<I + 1, N>::cmp(v1, v2));
  78. }
  79. };
  80. template <std::size_t N>
  81. struct greater_impl<N, N> {
  82. template <class T, class U>
  83. constexpr static bool cmp(const T&, const U&) noexcept {
  84. return T::size_v > U::size_v;
  85. }
  86. };
  87. template <std::size_t I, std::size_t N>
  88. struct greater_equal_impl {
  89. template <class T, class U>
  90. constexpr static bool cmp(const T& v1, const U& v2) noexcept {
  91. return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
  92. || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_equal_impl<I + 1, N>::cmp(v1, v2));
  93. }
  94. };
  95. template <std::size_t N>
  96. struct greater_equal_impl<N, N> {
  97. template <class T, class U>
  98. constexpr static bool cmp(const T&, const U&) noexcept {
  99. return T::size_v >= U::size_v;
  100. }
  101. };
  102. template <typename SizeT>
  103. constexpr void hash_combine(SizeT& seed, SizeT value) noexcept {
  104. seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
  105. }
  106. template <typename T>
  107. auto compute_hash(const T& value, long /*priority*/)
  108. -> decltype(std::hash<T>()(value))
  109. {
  110. return std::hash<T>()(value);
  111. }
  112. template <typename T>
  113. std::size_t compute_hash(const T& /*value*/, int /*priority*/) {
  114. static_assert(sizeof(T) && false, "====================> Boost.PFR: std::hash not specialized for type T");
  115. return 0;
  116. }
  117. template <std::size_t I, std::size_t N>
  118. struct hash_impl {
  119. template <class T>
  120. constexpr static std::size_t compute(const T& val) noexcept {
  121. std::size_t h = detail::compute_hash( ::boost::pfr::detail::sequence_tuple::get<I>(val), 1L );
  122. detail::hash_combine(h, hash_impl<I + 1, N>::compute(val) );
  123. return h;
  124. }
  125. };
  126. template <std::size_t N>
  127. struct hash_impl<N, N> {
  128. template <class T>
  129. constexpr static std::size_t compute(const T&) noexcept {
  130. return 0;
  131. }
  132. };
  133. ///////////////////// Define min_element and to avoid inclusion of <algorithm>
  134. constexpr std::size_t min_size(std::size_t x, std::size_t y) noexcept {
  135. return x < y ? x : y;
  136. }
  137. template <template <std::size_t, std::size_t> class Visitor, class T, class U>
  138. constexpr bool binary_visit(const T& x, const U& y) {
  139. constexpr std::size_t fields_count_lhs = detail::fields_count<std::remove_reference_t<T>>();
  140. constexpr std::size_t fields_count_rhs = detail::fields_count<std::remove_reference_t<U>>();
  141. constexpr std::size_t fields_count_min = detail::min_size(fields_count_lhs, fields_count_rhs);
  142. typedef Visitor<0, fields_count_min> visitor_t;
  143. #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
  144. return visitor_t::cmp(detail::tie_as_tuple(x), detail::tie_as_tuple(y));
  145. #else
  146. bool result = true;
  147. ::boost::pfr::detail::for_each_field_dispatcher(
  148. x,
  149. [&result, &y](const auto& lhs) {
  150. ::boost::pfr::detail::for_each_field_dispatcher(
  151. y,
  152. [&result, &lhs](const auto& rhs) {
  153. result = visitor_t::cmp(lhs, rhs);
  154. },
  155. detail::make_index_sequence<fields_count_rhs>{}
  156. );
  157. },
  158. detail::make_index_sequence<fields_count_lhs>{}
  159. );
  160. return result;
  161. #endif
  162. }
  163. }}} // namespace boost::pfr::detail
  164. #endif // BOOST_PFR_DETAIL_FUNCTIONAL_HPP