3 Defines `boost::hana::range`.
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)
10 #ifndef BOOST_HANA_RANGE_HPP
11 #define BOOST_HANA_RANGE_HPP
13 #include <boost/hana/fwd/range.hpp>
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>
47 BOOST_HANA_NAMESPACE_BEGIN
48 //////////////////////////////////////////////////////////////////////////
50 //////////////////////////////////////////////////////////////////////////
52 template <typename T, T From, T To>
54 : detail::operators::adl<range<T, From, To>>
55 , detail::iterable_operators<range<T, From, To>>
57 static_assert(From <= To,
58 "hana::make_range(from, to) requires 'from <= to'");
61 static constexpr value_type from = From;
62 static constexpr value_type to = To;
66 template <typename T, T From, T To>
67 struct tag_of<range<T, From, To>> {
68 using type = range_tag;
71 //////////////////////////////////////////////////////////////////////////
73 //////////////////////////////////////////////////////////////////////////
75 struct make_impl<range_tag> {
76 template <typename From, typename To>
77 static constexpr auto apply(From const&, To const&) {
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");
83 static_assert(hana::IntegralConstant<To>::value,
84 "hana::make_range(from, to) requires 'to' to be an IntegralConstant");
87 using T = typename common<
88 typename hana::tag_of<From>::type::value_type,
89 typename hana::tag_of<To>::type::value_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>{};
97 //////////////////////////////////////////////////////////////////////////
99 //////////////////////////////////////////////////////////////////////////
102 struct comparable_operators<range_tag> {
103 static constexpr bool value = true;
107 //////////////////////////////////////////////////////////////////////////
109 //////////////////////////////////////////////////////////////////////////
111 struct equal_impl<range_tag, range_tag> {
112 template <typename R1, typename R2>
113 static constexpr auto apply(R1 const&, R2 const&) {
115 (R1::from == R1::to && R2::from == R2::to) ||
116 (R1::from == R2::from && R1::to == R2::to)
121 //////////////////////////////////////////////////////////////////////////
123 //////////////////////////////////////////////////////////////////////////
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>{}...);
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>{});
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)>; }
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>; }
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>; }
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) {
170 return n * (n+1) / 2;
174 return sum_helper(0, n) - sum_helper(0, m-1);
178 return sum_helper(0, n) - sum_helper(0, -m);
182 return -sum_helper(-n, -m);
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)>;
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) {
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)>; }
211 //////////////////////////////////////////////////////////////////////////
213 //////////////////////////////////////////////////////////////////////////
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>);
222 template <typename T, T from, typename N>
223 static constexpr auto find_helper(hana::false_)
224 { return hana::nothing; }
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)>);
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)>;
242 //////////////////////////////////////////////////////////////////////////
244 //////////////////////////////////////////////////////////////////////////
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>; }
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>; }
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>;
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>; }
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>{};
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>{};
292 BOOST_HANA_NAMESPACE_END
294 #endif // !BOOST_HANA_RANGE_HPP