Here's how to do it. Given your template template some_other_type :
template<int I, int J> struct some_other_type { };
And given some of the mechanisms hidden in the detail namespace:
namespace detail { template<int... Is> struct pairs { }; template<int I, int J> struct pairs<I, J> { using type = std::tuple<some_other_type<I, J>>; }; template<int I, int J, int... Is> struct pairs<I, J, Is...> { using type = decltype(std::tuple_cat( std::tuple<some_other_type<I, J>>(), typename pairs<J, Is...>::type())); }; }
You can provide a simple function that instantiates an auxiliary class template:
template<int... Is> typename detail::pairs<Is...>::type pairs() { return typename detail::pairs<Is...>::type(); }
And here is how you use it (and test case):
#include <type_traits> int main() { auto p = pairs<1, 2, 3, 4>(); // Won't fire! static_assert( std::is_same< decltype(p), std::tuple< some_other_type<1,2>, some_other_type<2,3>, some_other_type<3,4>> >::value, "Error!"); }
Finally, here is a living example .
IMPROVEMENT: (why write <1, 2, 3, 4> when you can write <1, 5> )?
It is also possible to extend the above solution so that you do not need to manually record each number between the minimum and maximum as an argument to the pairs() template. Given the additional technique below, again hidden in the detail namespace:
namespace detail { template <int... Is> struct index_list { }; template <int MIN, int N, int... Is> struct range_builder; template <int MIN, int... Is> struct range_builder<MIN, MIN, Is...> { typedef index_list<Is...> type; }; template <int MIN, int N, int... Is> struct range_builder : public range_builder<MIN, N - 1, N - 1, Is...> { };
You can define an auxiliary function pairs_range() , which takes 2 template arguments defining the range [begin, end) -, where end not part of the standard library style:
template<int I, int J> auto pairs_range() -> decltype(pairs_range(detail::index_range<I, J>())) { return pairs_range(detail::index_range<I, J>()); }
And so it can be used (including a test case):
int main() {
And again, here is a living example .