/*============================================================================= Copyright (c) 2011-2019 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP #define SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP #include #include #include #include #include namespace sprout { namespace detail { template struct integer_range_default_step : public sprout::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_sequence {}; template struct integer_range_next_odd; template struct integer_range_next_odd, Next, Tail> : public sprout::integer_sequence {}; template::type Step, typename std::make_unsigned::type N, typename Enable = void> struct integer_range_dispatch; template::type Step, typename std::make_unsigned::type N> struct integer_range_dispatch< T, First, Step, N, typename std::enable_if<(N == 0)>::type > : public sprout::integer_sequence {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_dispatch< T, First, Step, N, typename std::enable_if<(N == 1)>::type > : public sprout::integer_sequence {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_dispatch< 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_dispatch::type, N / 2 * Step > {}; template::type Step, typename std::make_unsigned::type N> struct integer_range_dispatch< 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_dispatch::type, N / 2 * Step, First + (N - 1) * Step > {}; template::type Step, typename Enable = void> struct integer_range_impl {}; template::type Step> struct integer_range_impl< T, First, Last, Step, typename std::enable_if<((First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last))>::type > : public sprout::detail::integer_range_dispatch< T, First, Step, (static_cast::type>(Last - First) + (Step > 0 ? Step - 1 : Step + 1)) / Step > {}; template< typename T, T First, T Last, typename std::make_signed::type Step > struct integer_range : public sprout::enable_make_indexes< sprout::detail::integer_range_impl > { static_assert( (First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last), "(First < Last && Step > 0) || (First > Last && Step < 0) || (First == Last)" ); }; } // namespace detail // // integer_range // #if SPROUT_USE_TEMPLATE_ALIASES && !defined(SPROUT_WORKAROUND_NO_TEMPLATE_ARGUMENT_DEDUCTION_WITH_ALIASES) template< typename T, T First, T Last, typename std::make_signed::type Step = sprout::detail::integer_range_default_step::value > using integer_range = typename sprout::detail::integer_range::type; #else // #if SPROUT_USE_TEMPLATE_ALIASES && !defined(SPROUT_WORKAROUND_NO_TEMPLATE_ARGUMENT_DEDUCTION_WITH_ALIASES) 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::detail::integer_range {}; #endif // #if SPROUT_USE_TEMPLATE_ALIASES && !defined(SPROUT_WORKAROUND_NO_TEMPLATE_ARGUMENT_DEDUCTION_WITH_ALIASES) } // namespace sprout #endif // #ifndef SPROUT_INDEX_TUPLE_INTEGER_RANGE_HPP