]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/hana/range.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / hana / range.hpp
1 /*!
2 @file
3 Defines `boost::hana::range`.
4
5 @copyright Louis Dionne 2013-2017
6 Distributed under the Boost Software License, Version 1.0.
7 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
8 */
9
10 #ifndef BOOST_HANA_RANGE_HPP
11 #define BOOST_HANA_RANGE_HPP
12
13 #include <boost/hana/fwd/range.hpp>
14
15 #include <boost/hana/bool.hpp>
16 #include <boost/hana/concept/integral_constant.hpp>
17 #include <boost/hana/config.hpp>
18 #include <boost/hana/core/common.hpp>
19 #include <boost/hana/core/to.hpp>
20 #include <boost/hana/core/tag_of.hpp>
21 #include <boost/hana/detail/operators/adl.hpp>
22 #include <boost/hana/detail/operators/comparable.hpp>
23 #include <boost/hana/detail/operators/iterable.hpp>
24 #include <boost/hana/fwd/at.hpp>
25 #include <boost/hana/fwd/back.hpp>
26 #include <boost/hana/fwd/contains.hpp>
27 #include <boost/hana/fwd/drop_front.hpp>
28 #include <boost/hana/fwd/drop_front_exactly.hpp>
29 #include <boost/hana/fwd/equal.hpp>
30 #include <boost/hana/fwd/find.hpp>
31 #include <boost/hana/fwd/front.hpp>
32 #include <boost/hana/fwd/is_empty.hpp>
33 #include <boost/hana/fwd/length.hpp>
34 #include <boost/hana/fwd/maximum.hpp>
35 #include <boost/hana/fwd/minimum.hpp>
36 #include <boost/hana/fwd/product.hpp>
37 #include <boost/hana/fwd/sum.hpp>
38 #include <boost/hana/fwd/unpack.hpp>
39 #include <boost/hana/integral_constant.hpp> // required by fwd decl and below
40 #include <boost/hana/optional.hpp>
41 #include <boost/hana/value.hpp>
42
43 #include <cstddef>
44 #include <utility>
45
46
47 BOOST_HANA_NAMESPACE_BEGIN
48 //////////////////////////////////////////////////////////////////////////
49 // range<>
50 //////////////////////////////////////////////////////////////////////////
51 //! @cond
52 template <typename T, T From, T To>
53 struct range
54 : detail::operators::adl<range<T, From, To>>
55 , detail::iterable_operators<range<T, From, To>>
56 {
57 static_assert(From <= To,
58 "hana::make_range(from, to) requires 'from <= to'");
59
60 using value_type = T;
61 static constexpr value_type from = From;
62 static constexpr value_type to = To;
63 };
64 //! @endcond
65
66 template <typename T, T From, T To>
67 struct tag_of<range<T, From, To>> {
68 using type = range_tag;
69 };
70
71 //////////////////////////////////////////////////////////////////////////
72 // make<range_tag>
73 //////////////////////////////////////////////////////////////////////////
74 template <>
75 struct make_impl<range_tag> {
76 template <typename From, typename To>
77 static constexpr auto apply(From const&, To const&) {
78
79 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
80 static_assert(hana::IntegralConstant<From>::value,
81 "hana::make_range(from, to) requires 'from' to be an IntegralConstant");
82
83 static_assert(hana::IntegralConstant<To>::value,
84 "hana::make_range(from, to) requires 'to' to be an IntegralConstant");
85 #endif
86
87 using T = typename common<
88 typename hana::tag_of<From>::type::value_type,
89 typename hana::tag_of<To>::type::value_type
90 >::type;
91 constexpr T from = hana::to<T>(From::value);
92 constexpr T to = hana::to<T>(To::value);
93 return range<T, from, to>{};
94 }
95 };
96
97 //////////////////////////////////////////////////////////////////////////
98 // Operators
99 //////////////////////////////////////////////////////////////////////////
100 namespace detail {
101 template <>
102 struct comparable_operators<range_tag> {
103 static constexpr bool value = true;
104 };
105 }
106
107 //////////////////////////////////////////////////////////////////////////
108 // Comparable
109 //////////////////////////////////////////////////////////////////////////
110 template <>
111 struct equal_impl<range_tag, range_tag> {
112 template <typename R1, typename R2>
113 static constexpr auto apply(R1 const&, R2 const&) {
114 return hana::bool_c<
115 (R1::from == R1::to && R2::from == R2::to) ||
116 (R1::from == R2::from && R1::to == R2::to)
117 >;
118 }
119 };
120
121 //////////////////////////////////////////////////////////////////////////
122 // Foldable
123 //////////////////////////////////////////////////////////////////////////
124 template <>
125 struct unpack_impl<range_tag> {
126 template <typename T, T from, typename F, T ...v>
127 static constexpr decltype(auto)
128 unpack_helper(F&& f, std::integer_sequence<T, v...>) {
129 return static_cast<F&&>(f)(integral_constant<T, from + v>{}...);
130 }
131
132 template <typename T, T from, T to, typename F>
133 static constexpr decltype(auto) apply(range<T, from, to> const&, F&& f) {
134 return unpack_helper<T, from>(static_cast<F&&>(f),
135 std::make_integer_sequence<T, to - from>{});
136 }
137 };
138
139 template <>
140 struct length_impl<range_tag> {
141 template <typename T, T from, T to>
142 static constexpr auto apply(range<T, from, to> const&)
143 { return hana::size_c<static_cast<std::size_t>(to - from)>; }
144 };
145
146 template <>
147 struct minimum_impl<range_tag> {
148 template <typename T, T from, T to>
149 static constexpr auto apply(range<T, from, to> const&)
150 { return integral_c<T, from>; }
151 };
152
153 template <>
154 struct maximum_impl<range_tag> {
155 template <typename T, T from, T to>
156 static constexpr auto apply(range<T, from, to> const&)
157 { return integral_c<T, to-1>; }
158 };
159
160 template <>
161 struct sum_impl<range_tag> {
162 // Returns the sum of `[m, n]`, where `m <= n` always hold.
163 template <typename I>
164 static constexpr I sum_helper(I m, I n) {
165 if (m == n)
166 return m;
167
168 // 0 == m < n
169 else if (0 == m)
170 return n * (n+1) / 2;
171
172 // 0 < m < n
173 else if (0 < m)
174 return sum_helper(0, n) - sum_helper(0, m-1);
175
176 // m < 0 <= n
177 else if (0 <= n)
178 return sum_helper(0, n) - sum_helper(0, -m);
179
180 // m < n < 0
181 else
182 return -sum_helper(-n, -m);
183 }
184
185 template <typename, typename T, T from, T to>
186 static constexpr auto apply(range<T, from, to> const&) {
187 return integral_c<T, from == to ? 0 : sum_helper(from, to-1)>;
188 }
189 };
190
191 template <>
192 struct product_impl<range_tag> {
193 // Returns the product of `[m, n)`, where `m <= n` always hold.
194 template <typename I>
195 static constexpr I product_helper(I m, I n) {
196 if (m <= 0 && 0 < n)
197 return 0;
198 else {
199 I p = 1;
200 for (; m != n; ++m)
201 p *= m;
202 return p;
203 }
204 }
205
206 template <typename, typename T, T from, T to>
207 static constexpr auto apply(range<T, from, to> const&)
208 { return integral_c<T, product_helper(from, to)>; }
209 };
210
211 //////////////////////////////////////////////////////////////////////////
212 // Searchable
213 //////////////////////////////////////////////////////////////////////////
214 template <>
215 struct find_impl<range_tag> {
216 template <typename T, T from, typename N>
217 static constexpr auto find_helper(hana::true_) {
218 constexpr T n = N::value;
219 return hana::just(hana::integral_c<T, n>);
220 }
221
222 template <typename T, T from, typename N>
223 static constexpr auto find_helper(hana::false_)
224 { return hana::nothing; }
225
226 template <typename T, T from, T to, typename N>
227 static constexpr auto apply(range<T, from, to> const&, N const&) {
228 constexpr auto n = N::value;
229 return find_helper<T, from, N>(hana::bool_c<(n >= from && n < to)>);
230 }
231 };
232
233 template <>
234 struct contains_impl<range_tag> {
235 template <typename T, T from, T to, typename N>
236 static constexpr auto apply(range<T, from, to> const&, N const&) {
237 constexpr auto n = N::value;
238 return bool_c<(n >= from && n < to)>;
239 }
240 };
241
242 //////////////////////////////////////////////////////////////////////////
243 // Iterable
244 //////////////////////////////////////////////////////////////////////////
245 template <>
246 struct front_impl<range_tag> {
247 template <typename T, T from, T to>
248 static constexpr auto apply(range<T, from, to> const&)
249 { return integral_c<T, from>; }
250 };
251
252 template <>
253 struct is_empty_impl<range_tag> {
254 template <typename T, T from, T to>
255 static constexpr auto apply(range<T, from, to> const&)
256 { return bool_c<from == to>; }
257 };
258
259 template <>
260 struct at_impl<range_tag> {
261 template <typename T, T from, T to, typename N>
262 static constexpr auto apply(range<T, from, to> const&, N const&) {
263 constexpr auto n = N::value;
264 return integral_c<T, from + n>;
265 }
266 };
267
268 template <>
269 struct back_impl<range_tag> {
270 template <typename T, T from, T to>
271 static constexpr auto apply(range<T, from, to> const&)
272 { return integral_c<T, to - 1>; }
273 };
274
275 template <>
276 struct drop_front_impl<range_tag> {
277 template <typename T, T from, T to, typename N>
278 static constexpr auto apply(range<T, from, to> const&, N const&) {
279 constexpr auto n = N::value;
280 return range<T, (to < from + n ? to : from + n), to>{};
281 }
282 };
283
284 template <>
285 struct drop_front_exactly_impl<range_tag> {
286 template <typename T, T from, T to, typename N>
287 static constexpr auto apply(range<T, from, to> const&, N const&) {
288 constexpr auto n = N::value;
289 return range<T, from + n, to>{};
290 }
291 };
292 BOOST_HANA_NAMESPACE_END
293
294 #endif // !BOOST_HANA_RANGE_HPP