Template integer range, version 2
My main objection to your code is:

Principle of Least Surprise

I was pretty surprised that:

make_index_range&lt;15u, 0u, 3u&gt;


is the sequence

std::index_sequence&lt;15, 12, 9, 6, 3&gt;


given that it sure looks like we're going from 15 to 0 by 3s... which intuitively should produce std::index_sequence&lt;&gt;. You already do correctly provide two type aliases, where make_index_range is an alias for make_integer_range... so if somebody wants a negative range, they should have to do:

make_integer_range&lt;int, 15, 0, -3&gt;.


That change will also simplify your implementation, which leads into...

Simplify, Simplify, Simplify

Once you drop the increasing/decreasing check, the code becomes simpler. We are always going from Begin to End by Step. 

First, let's determine the size of our sequence. For signed integers, we can just divide by Step and floor at 0. For unsigned integers, we have to ensure that End is at least as big as Begin:

template &lt;class T, T Begin, T End, T Step&gt;
struct sequence_size
: std::conditional_t&lt;
        std::is_signed&lt;T&gt;::value,
        std::integral_constant&lt;T, std::max&lt;T&gt;(0, (End - Begin)/Step)&gt;,
        std::integral_constant&lt;T, (End &gt;= Begin) ? (End - Begin)/Step : 0&gt;
        &gt;
{ };


And then, with a default template parameter, our detail::make_integer_range can just be a simple pack expansion. No need for separate cases for increasing/decreasing sequences, since that would be handled by simply having a negative Step for signed integral types:

namespace detail {
    template &lt;class T, T Begin, T End, T Step, 
        typename = std::make_integer_sequence&lt;T, sequence_size&lt;T, Begin, End, Step&gt;::value&gt;
        &gt;
    struct make_integer_range;

    template &lt;class T, T Begin, T End, T Step, T... Idx&gt;
    struct make_integer_range&lt;T, Begin, End, Step, std::integer_sequence&lt;T, Idx...&gt;&gt;
    {
        using type = std::integer_sequence&lt;T, Idx * Step + Begin...&gt;;
    };
}

template &lt;class T, T Begin, T End, T Step&gt;
using make_integer_range = typename detail::make_integer_range&lt;T, Begin, End, Step&gt;::type;

template &lt;std::size_t Begin, std::size_t End, std::size_t Step&gt;
using make_index_range = make_integer_range&lt;std::size_t, Begin, End, Step&gt;;


Add Default Step

Using 1 as a default is pretty standard, so let's just do that:

template &lt;class T, T Begin, T End, T Step=1&gt;
using make_integer_range = typename detail::make_integer_range&lt;T, Begin, End, Step&gt;::type;

template &lt;std::size_t Begin, std::size_t End, std::size_t Step=1&gt;
using make_index_range = make_integer_range&lt;std::size_t, Begin, End, Step&gt;;


Add Default Start

You could also provide a default beginning by having your aliases take a pack of ints. Something like:

template &lt;class T, T... Vals&gt;
using make_integer_range = typename detail::make_integer_range_variadic&lt;T, Vals...&gt;::type;

template &lt;std::size_t... Vals&gt;
using make_index_range = make_integer_range&lt;std::size_t, Vals...&gt;;


With:

template &lt;class T, T... Vals&gt;
struct make_integer_range_variadic
: make_integer_range&lt;T, Vals...&gt;
{ };

template &lt;class T, T End&gt;
struct make_integer_range_variadic&lt;T, End&gt;
: make_integer_range&lt;T, 0, End, 1&gt;
{ };

template &lt;class T, T Begin, T End&gt;
struct make_integer_range_variadic&lt;T, Begin, End&gt;
: make_integer_range&lt;T, Begin, End, 1&gt;
{ };


This would allow:

make_index_range&lt;5&gt;       ==&gt; &lt;0, 1, 2, 3, 4&gt;
make_index_range&lt;2, 5&gt;    ==&gt; &lt;2, 3, 4&gt;
make_index_range&lt;2, 5, 2&gt; ==&gt; &lt;2, 4&gt;


YMMV on whether or not you want to allow this, but just throwing this out as an option in case you do.