File indexing completed on 2025-01-30 09:43:39
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_HANA_RANGE_HPP
0011 #define BOOST_HANA_RANGE_HPP
0012
0013 #include <boost/hana/fwd/range.hpp>
0014
0015 #include <boost/hana/bool.hpp>
0016 #include <boost/hana/concept/integral_constant.hpp>
0017 #include <boost/hana/config.hpp>
0018 #include <boost/hana/core/common.hpp>
0019 #include <boost/hana/core/to.hpp>
0020 #include <boost/hana/core/tag_of.hpp>
0021 #include <boost/hana/detail/operators/adl.hpp>
0022 #include <boost/hana/detail/operators/comparable.hpp>
0023 #include <boost/hana/detail/operators/iterable.hpp>
0024 #include <boost/hana/fwd/at.hpp>
0025 #include <boost/hana/fwd/back.hpp>
0026 #include <boost/hana/fwd/contains.hpp>
0027 #include <boost/hana/fwd/drop_front.hpp>
0028 #include <boost/hana/fwd/drop_front_exactly.hpp>
0029 #include <boost/hana/fwd/equal.hpp>
0030 #include <boost/hana/fwd/find.hpp>
0031 #include <boost/hana/fwd/front.hpp>
0032 #include <boost/hana/fwd/is_empty.hpp>
0033 #include <boost/hana/fwd/length.hpp>
0034 #include <boost/hana/fwd/maximum.hpp>
0035 #include <boost/hana/fwd/minimum.hpp>
0036 #include <boost/hana/fwd/product.hpp>
0037 #include <boost/hana/fwd/sum.hpp>
0038 #include <boost/hana/fwd/unpack.hpp>
0039 #include <boost/hana/integral_constant.hpp> // required by fwd decl and below
0040 #include <boost/hana/optional.hpp>
0041 #include <boost/hana/value.hpp>
0042
0043 #include <cstddef>
0044 #include <utility>
0045
0046
0047 namespace boost { namespace hana {
0048
0049
0050
0051
0052 template <typename T, T From, T To>
0053 struct range
0054 : detail::operators::adl<range<T, From, To>>
0055 , detail::iterable_operators<range<T, From, To>>
0056 {
0057 static_assert(From <= To,
0058 "hana::make_range(from, to) requires 'from <= to'");
0059
0060 using value_type = T;
0061 static constexpr value_type from = From;
0062 static constexpr value_type to = To;
0063 };
0064
0065
0066 template <typename T, T From, T To>
0067 struct tag_of<range<T, From, To>> {
0068 using type = range_tag;
0069 };
0070
0071
0072
0073
0074 template <>
0075 struct make_impl<range_tag> {
0076 template <typename From, typename To>
0077 static constexpr auto apply(From const&, To const&) {
0078
0079 #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
0080 static_assert(hana::IntegralConstant<From>::value,
0081 "hana::make_range(from, to) requires 'from' to be an IntegralConstant");
0082
0083 static_assert(hana::IntegralConstant<To>::value,
0084 "hana::make_range(from, to) requires 'to' to be an IntegralConstant");
0085 #endif
0086
0087 using T = typename common<
0088 typename hana::tag_of<From>::type::value_type,
0089 typename hana::tag_of<To>::type::value_type
0090 >::type;
0091 constexpr T from = hana::to<T>(From::value);
0092 constexpr T to = hana::to<T>(To::value);
0093 return range<T, from, to>{};
0094 }
0095 };
0096
0097
0098
0099
0100 namespace detail {
0101 template <>
0102 struct comparable_operators<range_tag> {
0103 static constexpr bool value = true;
0104 };
0105 }
0106
0107
0108
0109
0110 template <>
0111 struct equal_impl<range_tag, range_tag> {
0112 template <typename R1, typename R2>
0113 static constexpr auto apply(R1 const&, R2 const&) {
0114 return hana::bool_c<
0115 (R1::from == R1::to && R2::from == R2::to) ||
0116 (R1::from == R2::from && R1::to == R2::to)
0117 >;
0118 }
0119 };
0120
0121
0122
0123
0124 template <>
0125 struct unpack_impl<range_tag> {
0126 template <typename T, T from, typename F, T ...v>
0127 static constexpr decltype(auto)
0128 unpack_helper(F&& f, std::integer_sequence<T, v...>) {
0129 return static_cast<F&&>(f)(integral_constant<T, from + v>{}...);
0130 }
0131
0132 template <typename T, T from, T to, typename F>
0133 static constexpr decltype(auto) apply(range<T, from, to> const&, F&& f) {
0134 return unpack_helper<T, from>(static_cast<F&&>(f),
0135 std::make_integer_sequence<T, to - from>{});
0136 }
0137 };
0138
0139 template <>
0140 struct length_impl<range_tag> {
0141 template <typename T, T from, T to>
0142 static constexpr auto apply(range<T, from, to> const&)
0143 { return hana::size_c<static_cast<std::size_t>(to - from)>; }
0144 };
0145
0146 template <>
0147 struct minimum_impl<range_tag> {
0148 template <typename T, T from, T to>
0149 static constexpr auto apply(range<T, from, to> const&)
0150 { return integral_c<T, from>; }
0151 };
0152
0153 template <>
0154 struct maximum_impl<range_tag> {
0155 template <typename T, T from, T to>
0156 static constexpr auto apply(range<T, from, to> const&)
0157 { return integral_c<T, to-1>; }
0158 };
0159
0160 template <>
0161 struct sum_impl<range_tag> {
0162
0163 template <typename I>
0164 static constexpr I sum_helper(I m, I n) {
0165 if (m == n)
0166 return m;
0167
0168
0169 else if (0 == m)
0170 return n * (n+1) / 2;
0171
0172
0173 else if (0 < m)
0174 return sum_helper(0, n) - sum_helper(0, m-1);
0175
0176
0177 else if (0 <= n)
0178 return sum_helper(0, n) - sum_helper(0, -m);
0179
0180
0181 else
0182 return -sum_helper(-n, -m);
0183 }
0184
0185 template <typename, typename T, T from, T to>
0186 static constexpr auto apply(range<T, from, to> const&) {
0187 return integral_c<T, from == to ? 0 : sum_helper(from, to-1)>;
0188 }
0189 };
0190
0191 template <>
0192 struct product_impl<range_tag> {
0193
0194 template <typename I>
0195 static constexpr I product_helper(I m, I n) {
0196 if (m <= 0 && 0 < n)
0197 return 0;
0198 else {
0199 I p = 1;
0200 for (; m != n; ++m)
0201 p *= m;
0202 return p;
0203 }
0204 }
0205
0206 template <typename, typename T, T from, T to>
0207 static constexpr auto apply(range<T, from, to> const&)
0208 { return integral_c<T, product_helper(from, to)>; }
0209 };
0210
0211
0212
0213
0214 template <>
0215 struct find_impl<range_tag> {
0216 template <typename T, T from, typename N>
0217 static constexpr auto find_helper(hana::true_) {
0218 constexpr T n = N::value;
0219 return hana::just(hana::integral_c<T, n>);
0220 }
0221
0222 template <typename T, T from, typename N>
0223 static constexpr auto find_helper(hana::false_)
0224 { return hana::nothing; }
0225
0226 template <typename T, T from, T to, typename N>
0227 static constexpr auto apply(range<T, from, to> const&, N const&) {
0228 constexpr auto n = N::value;
0229 return find_helper<T, from, N>(hana::bool_c<(n >= from && n < to)>);
0230 }
0231 };
0232
0233 template <>
0234 struct contains_impl<range_tag> {
0235 template <typename T, T from, T to, typename N>
0236 static constexpr auto apply(range<T, from, to> const&, N const&) {
0237 constexpr auto n = N::value;
0238 return bool_c<(n >= from && n < to)>;
0239 }
0240 };
0241
0242
0243
0244
0245 template <>
0246 struct front_impl<range_tag> {
0247 template <typename T, T from, T to>
0248 static constexpr auto apply(range<T, from, to> const&)
0249 { return integral_c<T, from>; }
0250 };
0251
0252 template <>
0253 struct is_empty_impl<range_tag> {
0254 template <typename T, T from, T to>
0255 static constexpr auto apply(range<T, from, to> const&)
0256 { return bool_c<from == to>; }
0257 };
0258
0259 template <>
0260 struct at_impl<range_tag> {
0261 template <typename T, T from, T to, typename N>
0262 static constexpr auto apply(range<T, from, to> const&, N const&) {
0263 constexpr auto n = N::value;
0264 return integral_c<T, from + n>;
0265 }
0266 };
0267
0268 template <>
0269 struct back_impl<range_tag> {
0270 template <typename T, T from, T to>
0271 static constexpr auto apply(range<T, from, to> const&)
0272 { return integral_c<T, to - 1>; }
0273 };
0274
0275 template <>
0276 struct drop_front_impl<range_tag> {
0277 template <typename T, T from, T to, typename N>
0278 static constexpr auto apply(range<T, from, to> const&, N const&) {
0279 constexpr auto n = N::value;
0280 return range<T, (to < from + n ? to : from + n), to>{};
0281 }
0282 };
0283
0284 template <>
0285 struct drop_front_exactly_impl<range_tag> {
0286 template <typename T, T from, T to, typename N>
0287 static constexpr auto apply(range<T, from, to> const&, N const&) {
0288 constexpr auto n = N::value;
0289 return range<T, from + n, to>{};
0290 }
0291 };
0292 }}
0293
0294 #endif