Your sample code is incorrect even if it compiles (i.e. when sizeof ... (Xs) == sizeof ... (Ys)). Say you have N-ary tuples, then jump_table has N * N elements, but only the first N elements are initialized by the ptrs function.
First, you need to combine two type lists:
template<class A, class B> struct P; template<class... Ts> struct L {}; template<class T, class... Ts> using mul = L<P<T, Ts>...>; template<class...> struct cat; template<class T> struct cat<T> { using type = T; }; template<class... As, class... Bs> struct cat<L<As...>, L<Bs...>> { using type = L<As..., Bs...>; }; template<class A, class B, class... Ts> struct cat<A, B, Ts...> { using type = typename cat<typename cat<A, B>::type, Ts...>::type; }; template<class A, class B> struct join; template<class... As, class... Bs> struct join<L<As...>, L<Bs...>> { using type = typename cat<mul<As, Bs...>...>::type; };
eg,
join<L<int[1], int[2]>, L<float[1], float[2], float[3]>>::type
gives you
L<P<int[1], float[1]>, P<int[1], float[2]>, P<int[1], float[3]>, P<int[2], float[1]>, P<int[2], float[2]>, P<int[2], float[3]>
Back to your example:
template <typename X, typename Y> void foo() {} template<class T, std::size_t N> struct jump_table { template<class... As, class... Bs> constexpr jump_table(L<P<As, Bs>...>) : table{&foo<As, Bs>...} {} T table[N]; }; template <typename... Xs, typename... Ys> void bar(const std::tuple<Xs...>&, const std::tuple<Ys...>&) { using fun_ptr_type = void (*) (void); static constexpr jump_table<fun_ptr_type, sizeof...(Xs) * sizeof...(Ys)> table = {typename join<L<Xs...>, L<Ys...>>::type()}; } int main () { using tuple0 = std::tuple<int, char, double>; using tuple1 = std::tuple<float, unsigned long>; bar(tuple0{}, tuple1{}); }
This should do what you expected.