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