| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | /*!@fileDefines `boost::hana::range`.@copyright Louis Dionne 2013-2017Distributed 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>BOOST_HANA_NAMESPACE_BEGIN    //////////////////////////////////////////////////////////////////////////    // 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>{};        }    };BOOST_HANA_NAMESPACE_END#endif // !BOOST_HANA_RANGE_HPP
 |