#include <type_traits>

namespace tile {
template<int...>
struct index_sequence {};

template<int N, int... Us>
struct make_index_sequence_helper : public make_index_sequence_helper<N - 1, N - 1, Us...> {};

template<>
struct make_index_sequence_helper<0> {
    using type = index_sequence<>;
};

template<int... Us>
struct make_index_sequence_helper<0, Us...> {
    using type = index_sequence<Us...>;
};

template<int N>
using make_index_sequence_t = typename make_index_sequence_helper<N>::type;

template<typename... Ts, typename IS = make_index_sequence_t<sizeof...(Ts)>>
IS
index_sequence_for()
{
    return IS();
}

static_assert(std::is_same<make_index_sequence_t<0>, index_sequence<>>::value, "");
static_assert(std::is_same<make_index_sequence_t<1>, index_sequence<0>>::value, "");
static_assert(std::is_same<make_index_sequence_t<2>, index_sequence<0, 1>>::value, "");

static_assert(std::is_same<decltype(index_sequence_for<>()), index_sequence<>>::value, "");
static_assert(std::is_same<decltype(index_sequence_for<int>()), index_sequence<0>>::value, "");
static_assert(std::is_same<decltype(index_sequence_for<int, char>()), index_sequence<0, 1>>::value, "");
}// namespace tile
