File indexing completed on 2025-01-18 09:43:38
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PFR_DETAIL_FUNCTIONAL_HPP
0007 #define BOOST_PFR_DETAIL_FUNCTIONAL_HPP
0008 #pragma once
0009
0010 #include <boost/pfr/detail/config.hpp>
0011
0012 #include <functional>
0013 #include <cstdint>
0014
0015 #include <boost/pfr/detail/sequence_tuple.hpp>
0016
0017 namespace boost { namespace pfr { namespace detail {
0018 template <std::size_t I, std::size_t N>
0019 struct equal_impl {
0020 template <class T, class U>
0021 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0022 return ::boost::pfr::detail::sequence_tuple::get<I>(v1) == ::boost::pfr::detail::sequence_tuple::get<I>(v2)
0023 && equal_impl<I + 1, N>::cmp(v1, v2);
0024 }
0025 };
0026
0027 template <std::size_t N>
0028 struct equal_impl<N, N> {
0029 template <class T, class U>
0030 constexpr static bool cmp(const T&, const U&) noexcept {
0031 return T::size_v == U::size_v;
0032 }
0033 };
0034
0035 template <std::size_t I, std::size_t N>
0036 struct not_equal_impl {
0037 template <class T, class U>
0038 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0039 return ::boost::pfr::detail::sequence_tuple::get<I>(v1) != ::boost::pfr::detail::sequence_tuple::get<I>(v2)
0040 || not_equal_impl<I + 1, N>::cmp(v1, v2);
0041 }
0042 };
0043
0044 template <std::size_t N>
0045 struct not_equal_impl<N, N> {
0046 template <class T, class U>
0047 constexpr static bool cmp(const T&, const U&) noexcept {
0048 return T::size_v != U::size_v;
0049 }
0050 };
0051
0052 template <std::size_t I, std::size_t N>
0053 struct less_impl {
0054 template <class T, class U>
0055 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0056 return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
0057 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_impl<I + 1, N>::cmp(v1, v2));
0058 }
0059 };
0060
0061 template <std::size_t N>
0062 struct less_impl<N, N> {
0063 template <class T, class U>
0064 constexpr static bool cmp(const T&, const U&) noexcept {
0065 return T::size_v < U::size_v;
0066 }
0067 };
0068
0069 template <std::size_t I, std::size_t N>
0070 struct less_equal_impl {
0071 template <class T, class U>
0072 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0073 return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
0074 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_equal_impl<I + 1, N>::cmp(v1, v2));
0075 }
0076 };
0077
0078 template <std::size_t N>
0079 struct less_equal_impl<N, N> {
0080 template <class T, class U>
0081 constexpr static bool cmp(const T&, const U&) noexcept {
0082 return T::size_v <= U::size_v;
0083 }
0084 };
0085
0086 template <std::size_t I, std::size_t N>
0087 struct greater_impl {
0088 template <class T, class U>
0089 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0090 return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
0091 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_impl<I + 1, N>::cmp(v1, v2));
0092 }
0093 };
0094
0095 template <std::size_t N>
0096 struct greater_impl<N, N> {
0097 template <class T, class U>
0098 constexpr static bool cmp(const T&, const U&) noexcept {
0099 return T::size_v > U::size_v;
0100 }
0101 };
0102
0103 template <std::size_t I, std::size_t N>
0104 struct greater_equal_impl {
0105 template <class T, class U>
0106 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
0107 return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
0108 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_equal_impl<I + 1, N>::cmp(v1, v2));
0109 }
0110 };
0111
0112 template <std::size_t N>
0113 struct greater_equal_impl<N, N> {
0114 template <class T, class U>
0115 constexpr static bool cmp(const T&, const U&) noexcept {
0116 return T::size_v >= U::size_v;
0117 }
0118 };
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131 template <typename SizeT>
0132 constexpr void hash_combine(SizeT& seed, SizeT value) noexcept {
0133 seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
0134 }
0135
0136 constexpr auto rotl(std::uint32_t x, std::uint32_t r) noexcept {
0137 return (x << r) | (x >> (32 - r));
0138 }
0139
0140 constexpr void hash_combine(std::uint32_t& h1, std::uint32_t k1) noexcept {
0141 const std::uint32_t c1 = 0xcc9e2d51;
0142 const std::uint32_t c2 = 0x1b873593;
0143
0144 k1 *= c1;
0145 k1 = detail::rotl(k1,15);
0146 k1 *= c2;
0147
0148 h1 ^= k1;
0149 h1 = detail::rotl(h1,13);
0150 h1 = h1*5+0xe6546b64;
0151 }
0152
0153 #if defined(INT64_MIN) && defined(UINT64_MAX)
0154 constexpr void hash_combine(std::uint64_t& h, std::uint64_t k) noexcept {
0155 const std::uint64_t m = 0xc6a4a7935bd1e995ULL;
0156 const int r = 47;
0157
0158 k *= m;
0159 k ^= k >> r;
0160 k *= m;
0161
0162 h ^= k;
0163 h *= m;
0164
0165
0166
0167 h += 0xe6546b64;
0168 }
0169 #endif
0170
0171 template <typename T>
0172 auto compute_hash(const T& value, long )
0173 -> decltype(std::hash<T>()(value))
0174 {
0175 return std::hash<T>()(value);
0176 }
0177
0178 template <typename T>
0179 std::size_t compute_hash(const T& , int ) {
0180 static_assert(sizeof(T) && false, "====================> Boost.PFR: std::hash not specialized for type T");
0181 return 0;
0182 }
0183
0184 template <std::size_t I, std::size_t N>
0185 struct hash_impl {
0186 template <class T>
0187 constexpr static std::size_t compute(const T& val) noexcept {
0188 std::size_t h = detail::compute_hash( ::boost::pfr::detail::sequence_tuple::get<I>(val), 1L );
0189 detail::hash_combine(h, hash_impl<I + 1, N>::compute(val) );
0190 return h;
0191 }
0192 };
0193
0194 template <std::size_t N>
0195 struct hash_impl<N, N> {
0196 template <class T>
0197 constexpr static std::size_t compute(const T&) noexcept {
0198 return 0;
0199 }
0200 };
0201
0202
0203 constexpr std::size_t min_size(std::size_t x, std::size_t y) noexcept {
0204 return x < y ? x : y;
0205 }
0206
0207 template <template <std::size_t, std::size_t> class Visitor, class T, class U>
0208 constexpr bool binary_visit(const T& x, const U& y) {
0209 constexpr std::size_t fields_count_lhs = detail::fields_count<std::remove_reference_t<T>>();
0210 constexpr std::size_t fields_count_rhs = detail::fields_count<std::remove_reference_t<U>>();
0211 constexpr std::size_t fields_count_min = detail::min_size(fields_count_lhs, fields_count_rhs);
0212 typedef Visitor<0, fields_count_min> visitor_t;
0213
0214 #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
0215 return visitor_t::cmp(detail::tie_as_tuple(x), detail::tie_as_tuple(y));
0216 #else
0217 bool result = true;
0218 ::boost::pfr::detail::for_each_field_dispatcher(
0219 x,
0220 [&result, &y](const auto& lhs) {
0221 constexpr std::size_t fields_count_rhs_ = detail::fields_count<std::remove_reference_t<U>>();
0222 ::boost::pfr::detail::for_each_field_dispatcher(
0223 y,
0224 [&result, &lhs](const auto& rhs) {
0225 result = visitor_t::cmp(lhs, rhs);
0226 },
0227 detail::make_index_sequence<fields_count_rhs_>{}
0228 );
0229 },
0230 detail::make_index_sequence<fields_count_lhs>{}
0231 );
0232
0233 return result;
0234 #endif
0235 }
0236
0237 }}}
0238
0239 #endif