This was inspired by the Columbo decision. It uses the package extension syntax that I originally looked for, namely
using type = typename Merge<T, typename Component<T, P, Indices>::type...>::type;
As a result, Make can now be reused, first using Triple and then using Quadruple , so any number of Indices can be deployed at once. Here, Component is a template-template-template parameter passed to Make :
#include <type_traits> template <typename T, typename... Packs> struct Merge; template <typename T, template <T...> class P1, template <T...> class P2, T... Is, T... Js> struct Merge<T, P1<Is...>, P2<Js...>> { using type = P1<Is..., Js...>; }; template <typename T, typename Pack1, typename Pack2, typename... Packs> struct Merge<T, Pack1, Pack2, Packs...> { using type = typename Merge<T, Pack1, typename Merge<T, Pack2, Packs...>::type>::type; }; template <typename T, template <T...> class P, T I> struct Triple { using type = P<I+1, -3*I, I-1>; }; template <typename T, template <T...> class P, T I> struct Quadruple { using type = P<I+1, -3*I, I-1, I>; }; template <typename T, typename IndexPack, template <typename U, template <U...> class P, U I> class Component> struct Make; template <typename T, template <T...> class Z, T... Indices, template <typename U, template <U...> class P, U I> class Component> struct Make<T, Z<Indices...>, Component> { using type = typename Merge<T, typename Component<T, Z, Indices>::type...>::type; }; template <int...> class Pack; int main() { static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Triple>::type, Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>>::value, "false"); static_assert (std::is_same<Make<int, Pack<1,2,3,4>, Quadruple>::type, Pack<2,-3,0,1, 3,-6,1,2, 4,-9,2,3, 5,-12,3,4>>::value, "false"); }