I would simply reduce your integer_range
to a single, non-recursive call to std::integer_sequence
:
namespace details
{
template<typename Int, typename, Int S>
struct increasing_integer_range;
template<typename Int, Int... N, Int S>
struct increasing_integer_range<Int, std::integer_sequence<Int, N...>, S>
: std::integer_sequence<Int, N+S...>
{};
template<typename Int, typename, Int S>
struct decreasing_integer_range;
template<typename Int, Int... N, Int S>
struct decreasing_integer_range<Int, std::integer_sequence<Int, N...>, S>
: std::integer_sequence<Int, S-N...>
{};
}
template<typename Int, Int S, Int E, bool Increasing=(S<E)>
struct integer_range;
template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, true>:
details::increasing_integer_range<Int, std::make_integer_sequence<Int, E-S>, S>
{};
template<typename Int, Int S, Int E>
struct integer_range<Int, S, E, false>:
details::decreasing_integer_range<Int, std::make_integer_sequence<Int, S-E>, S>
{};
template<std::size_t S, std::size_t E>
using index_range = integer_range<std::size_t, S, E>;
Which I tested with:
template<std::size_t... N>
void dummy( const std::integer_sequence< std::size_t, N... >& );
int main()
{
dummy( index_range< 2, 5 >() );
dummy( index_range< 5, 2 >() );
}
getting the expected linker errors:
main.cpp:(.text.startup+0xa): undefined reference to `void dummy<2ul, 3ul, 4ul>(detail::integer_sequence<unsigned long, 2ul, 3ul, 4ul> const&)'
main.cpp:(.text.startup+0x14): undefined reference to `void dummy<5ul, 4ul, 3ul>(detail::integer_sequence<unsigned long, 5ul, 4ul, 3ul> const&)'
Live example (with own implementation of integer_sequence
, just skip the first part)