Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:43:39

0001 /*!
0002 @file
0003 Defines `boost::hana::range`.
0004 
0005 Copyright Louis Dionne 2013-2022
0006 Distributed under the Boost Software License, Version 1.0.
0007 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
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     // range<>
0050     //////////////////////////////////////////////////////////////////////////
0051     //! @cond
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     //! @endcond
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     // make<range_tag>
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     // Operators
0099     //////////////////////////////////////////////////////////////////////////
0100     namespace detail {
0101         template <>
0102         struct comparable_operators<range_tag> {
0103             static constexpr bool value = true;
0104         };
0105     }
0106 
0107     //////////////////////////////////////////////////////////////////////////
0108     // Comparable
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     // Foldable
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         // Returns the sum of `[m, n]`, where `m <= n` always hold.
0163         template <typename I>
0164         static constexpr I sum_helper(I m, I n) {
0165             if (m == n)
0166                 return m;
0167 
0168             // 0 == m < n
0169             else if (0 == m)
0170                 return n * (n+1) / 2;
0171 
0172             // 0 < m < n
0173             else if (0 < m)
0174                 return sum_helper(0, n) - sum_helper(0, m-1);
0175 
0176             // m < 0 <= n
0177             else if (0 <= n)
0178                 return sum_helper(0, n) - sum_helper(0, -m);
0179 
0180             // m < n < 0
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         // Returns the product of `[m, n)`, where `m <= n` always hold.
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     // Searchable
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     // Iterable
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 }} // end namespace boost::hana
0293 
0294 #endif // !BOOST_HANA_RANGE_HPP