#ifndef SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP #define SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP #include #include #include #include namespace sprout { namespace detail { template struct integer_range_default_step : public std::integral_constant::type, (First <= Last ? 1 : -1)> {}; } // namespace detail namespace detail { template struct integer_range_next_even; template struct integer_range_next_even, Next> : public sprout::integer_seq {}; template struct integer_range_next_odd; template struct integer_range_next_odd, Next, Tail> : public sprout::integer_seq {}; template::type Step, typename std::make_unsigned::type N, typename Enable = void> struct integer_range_impl; template::type Step, typename std::make_unsigned::type N> struct integer_range_impl< T, First, Step, N, typename std::enable_if<(N == 0)>::type > : public sprout::integer_seq {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_impl< T, First, Step, N, typename std::enable_if<(N == 1)>::type > : public sprout::integer_seq {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_impl< T, First, Step, N, typename std::enable_if<(N > 1 && N % 2 == 0)>::type > : public sprout::detail::integer_range_next_even< T, typename sprout::detail::integer_range_impl::type, N / 2 * Step > {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_impl< T, First, Step, N, typename std::enable_if<(N > 1 && N % 2 == 1)>::type > : public sprout::detail::integer_range_next_odd< T, typename sprout::detail::integer_range_impl::type, N / 2 * Step, First + (N - 1) * Step > {}; template::type Step, typename Enable = void> struct integer_range {}; template::type Step> struct integer_range< T, First, Last, Step, typename std::enable_if<((First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last))>::type > : public sprout::detail::integer_range_impl< T, First, Step, (static_cast::type>(Last - First) + (Step > 0 ? Step - 1 : Step + 1)) / Step > {}; } // namespace detail // // integer_range // template< typename T, T First, T Last, typename std::make_signed::type Step = sprout::detail::integer_range_default_step::value > struct integer_range : public sprout::enable_make_indexes< sprout::detail::integer_range > { static_assert( (First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last), "(First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last)" ); }; } // namespace sprout #endif // #ifndef SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP