]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/pfr/detail/functional.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / pfr / detail / functional.hpp
1 // Copyright (c) 2016-2022 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
6 #ifndef BOOST_PFR_DETAIL_FUNCTIONAL_HPP
7 #define BOOST_PFR_DETAIL_FUNCTIONAL_HPP
8 #pragma once
9
10 #include <boost/pfr/detail/config.hpp>
11
12 #include <functional>
13 #include <cstdint>
14
15 #include <boost/pfr/detail/sequence_tuple.hpp>
16
17 namespace boost { namespace pfr { namespace detail {
18 template <std::size_t I, std::size_t N>
19 struct equal_impl {
20 template <class T, class U>
21 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
22 return ::boost::pfr::detail::sequence_tuple::get<I>(v1) == ::boost::pfr::detail::sequence_tuple::get<I>(v2)
23 && equal_impl<I + 1, N>::cmp(v1, v2);
24 }
25 };
26
27 template <std::size_t N>
28 struct equal_impl<N, N> {
29 template <class T, class U>
30 constexpr static bool cmp(const T&, const U&) noexcept {
31 return T::size_v == U::size_v;
32 }
33 };
34
35 template <std::size_t I, std::size_t N>
36 struct not_equal_impl {
37 template <class T, class U>
38 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
39 return ::boost::pfr::detail::sequence_tuple::get<I>(v1) != ::boost::pfr::detail::sequence_tuple::get<I>(v2)
40 || not_equal_impl<I + 1, N>::cmp(v1, v2);
41 }
42 };
43
44 template <std::size_t N>
45 struct not_equal_impl<N, N> {
46 template <class T, class U>
47 constexpr static bool cmp(const T&, const U&) noexcept {
48 return T::size_v != U::size_v;
49 }
50 };
51
52 template <std::size_t I, std::size_t N>
53 struct less_impl {
54 template <class T, class U>
55 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
56 return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
57 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_impl<I + 1, N>::cmp(v1, v2));
58 }
59 };
60
61 template <std::size_t N>
62 struct less_impl<N, N> {
63 template <class T, class U>
64 constexpr static bool cmp(const T&, const U&) noexcept {
65 return T::size_v < U::size_v;
66 }
67 };
68
69 template <std::size_t I, std::size_t N>
70 struct less_equal_impl {
71 template <class T, class U>
72 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
73 return sequence_tuple::get<I>(v1) < sequence_tuple::get<I>(v2)
74 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && less_equal_impl<I + 1, N>::cmp(v1, v2));
75 }
76 };
77
78 template <std::size_t N>
79 struct less_equal_impl<N, N> {
80 template <class T, class U>
81 constexpr static bool cmp(const T&, const U&) noexcept {
82 return T::size_v <= U::size_v;
83 }
84 };
85
86 template <std::size_t I, std::size_t N>
87 struct greater_impl {
88 template <class T, class U>
89 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
90 return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
91 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_impl<I + 1, N>::cmp(v1, v2));
92 }
93 };
94
95 template <std::size_t N>
96 struct greater_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
103 template <std::size_t I, std::size_t N>
104 struct greater_equal_impl {
105 template <class T, class U>
106 constexpr static bool cmp(const T& v1, const U& v2) noexcept {
107 return sequence_tuple::get<I>(v1) > sequence_tuple::get<I>(v2)
108 || (sequence_tuple::get<I>(v1) == sequence_tuple::get<I>(v2) && greater_equal_impl<I + 1, N>::cmp(v1, v2));
109 }
110 };
111
112 template <std::size_t N>
113 struct greater_equal_impl<N, N> {
114 template <class T, class U>
115 constexpr static bool cmp(const T&, const U&) noexcept {
116 return T::size_v >= U::size_v;
117 }
118 };
119
120 // Hash combine functions copied from Boost.ContainerHash
121 // https://github.com/boostorg/container_hash/blob/171c012d4723c5e93cc7cffe42919afdf8b27dfa/include/boost/container_hash/hash.hpp#L311
122 // that is based on Peter Dimov's proposal
123 // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2005/n1756.pdf
124 // issue 6.18.
125 //
126 // This also contains public domain code from MurmurHash. From the
127 // MurmurHash header:
128 //
129 // MurmurHash3 was written by Austin Appleby, and is placed in the public
130 // domain. The author hereby disclaims copyright to this source code.
131 template <typename SizeT>
132 constexpr void hash_combine(SizeT& seed, SizeT value) noexcept {
133 seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
134 }
135
136 constexpr auto rotl(std::uint32_t x, std::uint32_t r) noexcept {
137 return (x << r) | (x >> (32 - r));
138 }
139
140 constexpr void hash_combine(std::uint32_t& h1, std::uint32_t k1) noexcept {
141 const std::uint32_t c1 = 0xcc9e2d51;
142 const std::uint32_t c2 = 0x1b873593;
143
144 k1 *= c1;
145 k1 = detail::rotl(k1,15);
146 k1 *= c2;
147
148 h1 ^= k1;
149 h1 = detail::rotl(h1,13);
150 h1 = h1*5+0xe6546b64;
151 }
152
153 #if defined(INT64_MIN) && defined(UINT64_MAX)
154 constexpr void hash_combine(std::uint64_t& h, std::uint64_t k) noexcept {
155 const std::uint64_t m = 0xc6a4a7935bd1e995ULL;
156 const int r = 47;
157
158 k *= m;
159 k ^= k >> r;
160 k *= m;
161
162 h ^= k;
163 h *= m;
164
165 // Completely arbitrary number, to prevent 0's
166 // from hashing to 0.
167 h += 0xe6546b64;
168 }
169 #endif
170
171 template <typename T>
172 auto compute_hash(const T& value, long /*priority*/)
173 -> decltype(std::hash<T>()(value))
174 {
175 return std::hash<T>()(value);
176 }
177
178 template <typename T>
179 std::size_t compute_hash(const T& /*value*/, int /*priority*/) {
180 static_assert(sizeof(T) && false, "====================> Boost.PFR: std::hash not specialized for type T");
181 return 0;
182 }
183
184 template <std::size_t I, std::size_t N>
185 struct hash_impl {
186 template <class T>
187 constexpr static std::size_t compute(const T& val) noexcept {
188 std::size_t h = detail::compute_hash( ::boost::pfr::detail::sequence_tuple::get<I>(val), 1L );
189 detail::hash_combine(h, hash_impl<I + 1, N>::compute(val) );
190 return h;
191 }
192 };
193
194 template <std::size_t N>
195 struct hash_impl<N, N> {
196 template <class T>
197 constexpr static std::size_t compute(const T&) noexcept {
198 return 0;
199 }
200 };
201
202 ///////////////////// Define min_element and to avoid inclusion of <algorithm>
203 constexpr std::size_t min_size(std::size_t x, std::size_t y) noexcept {
204 return x < y ? x : y;
205 }
206
207 template <template <std::size_t, std::size_t> class Visitor, class T, class U>
208 constexpr bool binary_visit(const T& x, const U& y) {
209 constexpr std::size_t fields_count_lhs = detail::fields_count<std::remove_reference_t<T>>();
210 constexpr std::size_t fields_count_rhs = detail::fields_count<std::remove_reference_t<U>>();
211 constexpr std::size_t fields_count_min = detail::min_size(fields_count_lhs, fields_count_rhs);
212 typedef Visitor<0, fields_count_min> visitor_t;
213
214 #if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE
215 return visitor_t::cmp(detail::tie_as_tuple(x), detail::tie_as_tuple(y));
216 #else
217 bool result = true;
218 ::boost::pfr::detail::for_each_field_dispatcher(
219 x,
220 [&result, &y](const auto& lhs) {
221 constexpr std::size_t fields_count_rhs_ = detail::fields_count<std::remove_reference_t<U>>();
222 ::boost::pfr::detail::for_each_field_dispatcher(
223 y,
224 [&result, &lhs](const auto& rhs) {
225 result = visitor_t::cmp(lhs, rhs);
226 },
227 detail::make_index_sequence<fields_count_rhs_>{}
228 );
229 },
230 detail::make_index_sequence<fields_count_lhs>{}
231 );
232
233 return result;
234 #endif
235 }
236
237 }}} // namespace boost::pfr::detail
238
239 #endif // BOOST_PFR_DETAIL_FUNCTIONAL_HPP