/*! @file Defines `boost::hana::range`. @copyright Louis Dionne 2013-2017 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // required by fwd decl and below #include #include #include #include namespace boost { namespace hana { ////////////////////////////////////////////////////////////////////////// // range<> ////////////////////////////////////////////////////////////////////////// //! @cond template struct range : detail::operators::adl> , detail::iterable_operators> { 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 struct tag_of> { using type = range_tag; }; ////////////////////////////////////////////////////////////////////////// // make ////////////////////////////////////////////////////////////////////////// template <> struct make_impl { template static constexpr auto apply(From const&, To const&) { #ifndef BOOST_HANA_CONFIG_DISABLE_CONCEPT_CHECKS static_assert(hana::IntegralConstant::value, "hana::make_range(from, to) requires 'from' to be an IntegralConstant"); static_assert(hana::IntegralConstant::value, "hana::make_range(from, to) requires 'to' to be an IntegralConstant"); #endif using T = typename common< typename hana::tag_of::type::value_type, typename hana::tag_of::type::value_type >::type; constexpr T from = hana::to(From::value); constexpr T to = hana::to(To::value); return range{}; } }; ////////////////////////////////////////////////////////////////////////// // Operators ////////////////////////////////////////////////////////////////////////// namespace detail { template <> struct comparable_operators { static constexpr bool value = true; }; } ////////////////////////////////////////////////////////////////////////// // Comparable ////////////////////////////////////////////////////////////////////////// template <> struct equal_impl { template 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 { template static constexpr decltype(auto) unpack_helper(F&& f, std::integer_sequence) { return static_cast(f)(integral_constant{}...); } template static constexpr decltype(auto) apply(range const&, F&& f) { return unpack_helper(static_cast(f), std::make_integer_sequence{}); } }; template <> struct length_impl { template static constexpr auto apply(range const&) { return hana::size_c(to - from)>; } }; template <> struct minimum_impl { template static constexpr auto apply(range const&) { return integral_c; } }; template <> struct maximum_impl { template static constexpr auto apply(range const&) { return integral_c; } }; template <> struct sum_impl { // Returns the sum of `[m, n]`, where `m <= n` always hold. template 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 static constexpr auto apply(range const&) { return integral_c; } }; template <> struct product_impl { // Returns the product of `[m, n)`, where `m <= n` always hold. template 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 static constexpr auto apply(range const&) { return integral_c; } }; ////////////////////////////////////////////////////////////////////////// // Searchable ////////////////////////////////////////////////////////////////////////// template <> struct find_impl { template static constexpr auto find_helper(hana::true_) { constexpr T n = N::value; return hana::just(hana::integral_c); } template static constexpr auto find_helper(hana::false_) { return hana::nothing; } template static constexpr auto apply(range const&, N const&) { constexpr auto n = N::value; return find_helper(hana::bool_c<(n >= from && n < to)>); } }; template <> struct contains_impl { template static constexpr auto apply(range const&, N const&) { constexpr auto n = N::value; return bool_c<(n >= from && n < to)>; } }; ////////////////////////////////////////////////////////////////////////// // Iterable ////////////////////////////////////////////////////////////////////////// template <> struct front_impl { template static constexpr auto apply(range const&) { return integral_c; } }; template <> struct is_empty_impl { template static constexpr auto apply(range const&) { return bool_c; } }; template <> struct at_impl { template static constexpr auto apply(range const&, N const&) { constexpr auto n = N::value; return integral_c; } }; template <> struct back_impl { template static constexpr auto apply(range const&) { return integral_c; } }; template <> struct drop_front_impl { template static constexpr auto apply(range const&, N const&) { constexpr auto n = N::value; return range{}; } }; template <> struct drop_front_exactly_impl { template static constexpr auto apply(range const&, N const&) { constexpr auto n = N::value; return range{}; } }; }} // end namespace boost::hana #endif // !BOOST_HANA_RANGE_HPP