123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- /*!
- @file
- Defines `boost::hana::range`.
- Copyright Louis Dionne 2013-2022
- Distributed under the Boost Software License, Version 1.0.
- (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
- */
- #ifndef BOOST_HANA_RANGE_HPP
- #define BOOST_HANA_RANGE_HPP
- #include <boost/hana/fwd/range.hpp>
- #include <boost/hana/bool.hpp>
- #include <boost/hana/concept/integral_constant.hpp>
- #include <boost/hana/config.hpp>
- #include <boost/hana/core/common.hpp>
- #include <boost/hana/core/to.hpp>
- #include <boost/hana/core/tag_of.hpp>
- #include <boost/hana/detail/operators/adl.hpp>
- #include <boost/hana/detail/operators/comparable.hpp>
- #include <boost/hana/detail/operators/iterable.hpp>
- #include <boost/hana/fwd/at.hpp>
- #include <boost/hana/fwd/back.hpp>
- #include <boost/hana/fwd/contains.hpp>
- #include <boost/hana/fwd/drop_front.hpp>
- #include <boost/hana/fwd/drop_front_exactly.hpp>
- #include <boost/hana/fwd/equal.hpp>
- #include <boost/hana/fwd/find.hpp>
- #include <boost/hana/fwd/front.hpp>
- #include <boost/hana/fwd/is_empty.hpp>
- #include <boost/hana/fwd/length.hpp>
- #include <boost/hana/fwd/maximum.hpp>
- #include <boost/hana/fwd/minimum.hpp>
- #include <boost/hana/fwd/product.hpp>
- #include <boost/hana/fwd/sum.hpp>
- #include <boost/hana/fwd/unpack.hpp>
- #include <boost/hana/integral_constant.hpp> // required by fwd decl and below
- #include <boost/hana/optional.hpp>
- #include <boost/hana/value.hpp>
- #include <cstddef>
- #include <utility>
- namespace boost { namespace hana {
- //////////////////////////////////////////////////////////////////////////
- // range<>
- //////////////////////////////////////////////////////////////////////////
- //! @cond
- template <typename T, T From, T To>
- struct range
- : detail::operators::adl<range<T, From, To>>
- , detail::iterable_operators<range<T, From, To>>
- {
- static_assert(From <= To,
- "hana::make_range(from, to) requires 'from <= to'");
- using value_type = T;
- static constexpr value_type from = From;
- static constexpr value_type to = To;
- };
- //! @endcond
- template <typename T, T From, T To>
- struct tag_of<range<T, From, To>> {
- using type = range_tag;
- };
- //////////////////////////////////////////////////////////////////////////
- // make<range_tag>
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct make_impl<range_tag> {
- template <typename From, typename To>
- static constexpr auto apply(From const&, To const&) {
- #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS
- static_assert(hana::IntegralConstant<From>::value,
- "hana::make_range(from, to) requires 'from' to be an IntegralConstant");
- static_assert(hana::IntegralConstant<To>::value,
- "hana::make_range(from, to) requires 'to' to be an IntegralConstant");
- #endif
- using T = typename common<
- typename hana::tag_of<From>::type::value_type,
- typename hana::tag_of<To>::type::value_type
- >::type;
- constexpr T from = hana::to<T>(From::value);
- constexpr T to = hana::to<T>(To::value);
- return range<T, from, to>{};
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Operators
- //////////////////////////////////////////////////////////////////////////
- namespace detail {
- template <>
- struct comparable_operators<range_tag> {
- static constexpr bool value = true;
- };
- }
- //////////////////////////////////////////////////////////////////////////
- // Comparable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct equal_impl<range_tag, range_tag> {
- template <typename R1, typename R2>
- static constexpr auto apply(R1 const&, R2 const&) {
- return hana::bool_c<
- (R1::from == R1::to && R2::from == R2::to) ||
- (R1::from == R2::from && R1::to == R2::to)
- >;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Foldable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct unpack_impl<range_tag> {
- template <typename T, T from, typename F, T ...v>
- static constexpr decltype(auto)
- unpack_helper(F&& f, std::integer_sequence<T, v...>) {
- return static_cast<F&&>(f)(integral_constant<T, from + v>{}...);
- }
- template <typename T, T from, T to, typename F>
- static constexpr decltype(auto) apply(range<T, from, to> const&, F&& f) {
- return unpack_helper<T, from>(static_cast<F&&>(f),
- std::make_integer_sequence<T, to - from>{});
- }
- };
- template <>
- struct length_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return hana::size_c<static_cast<std::size_t>(to - from)>; }
- };
- template <>
- struct minimum_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return integral_c<T, from>; }
- };
- template <>
- struct maximum_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return integral_c<T, to-1>; }
- };
- template <>
- struct sum_impl<range_tag> {
- // Returns the sum of `[m, n]`, where `m <= n` always hold.
- template <typename I>
- static constexpr I sum_helper(I m, I n) {
- if (m == n)
- return m;
- // 0 == m < n
- else if (0 == m)
- return n * (n+1) / 2;
- // 0 < m < n
- else if (0 < m)
- return sum_helper(0, n) - sum_helper(0, m-1);
- // m < 0 <= n
- else if (0 <= n)
- return sum_helper(0, n) - sum_helper(0, -m);
- // m < n < 0
- else
- return -sum_helper(-n, -m);
- }
- template <typename, typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&) {
- return integral_c<T, from == to ? 0 : sum_helper(from, to-1)>;
- }
- };
- template <>
- struct product_impl<range_tag> {
- // Returns the product of `[m, n)`, where `m <= n` always hold.
- template <typename I>
- static constexpr I product_helper(I m, I n) {
- if (m <= 0 && 0 < n)
- return 0;
- else {
- I p = 1;
- for (; m != n; ++m)
- p *= m;
- return p;
- }
- }
- template <typename, typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return integral_c<T, product_helper(from, to)>; }
- };
- //////////////////////////////////////////////////////////////////////////
- // Searchable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct find_impl<range_tag> {
- template <typename T, T from, typename N>
- static constexpr auto find_helper(hana::true_) {
- constexpr T n = N::value;
- return hana::just(hana::integral_c<T, n>);
- }
- template <typename T, T from, typename N>
- static constexpr auto find_helper(hana::false_)
- { return hana::nothing; }
- template <typename T, T from, T to, typename N>
- static constexpr auto apply(range<T, from, to> const&, N const&) {
- constexpr auto n = N::value;
- return find_helper<T, from, N>(hana::bool_c<(n >= from && n < to)>);
- }
- };
- template <>
- struct contains_impl<range_tag> {
- template <typename T, T from, T to, typename N>
- static constexpr auto apply(range<T, from, to> const&, N const&) {
- constexpr auto n = N::value;
- return bool_c<(n >= from && n < to)>;
- }
- };
- //////////////////////////////////////////////////////////////////////////
- // Iterable
- //////////////////////////////////////////////////////////////////////////
- template <>
- struct front_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return integral_c<T, from>; }
- };
- template <>
- struct is_empty_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return bool_c<from == to>; }
- };
- template <>
- struct at_impl<range_tag> {
- template <typename T, T from, T to, typename N>
- static constexpr auto apply(range<T, from, to> const&, N const&) {
- constexpr auto n = N::value;
- return integral_c<T, from + n>;
- }
- };
- template <>
- struct back_impl<range_tag> {
- template <typename T, T from, T to>
- static constexpr auto apply(range<T, from, to> const&)
- { return integral_c<T, to - 1>; }
- };
- template <>
- struct drop_front_impl<range_tag> {
- template <typename T, T from, T to, typename N>
- static constexpr auto apply(range<T, from, to> const&, N const&) {
- constexpr auto n = N::value;
- return range<T, (to < from + n ? to : from + n), to>{};
- }
- };
- template <>
- struct drop_front_exactly_impl<range_tag> {
- template <typename T, T from, T to, typename N>
- static constexpr auto apply(range<T, from, to> const&, N const&) {
- constexpr auto n = N::value;
- return range<T, from + n, to>{};
- }
- };
- }} // end namespace boost::hana
- #endif // !BOOST_HANA_RANGE_HPP
|