既存のタプルパックジェネレーターを使用するのがおそらく最も簡単です。
// Idiomatic tuple pack generator using successor method
template<int... I> struct tuple_pack {
using succ = tuple_pack<I..., sizeof...(I)>;
};
template<int N> struct make_tuple_pack {
using type = typename make_tuple_pack<N - 1>::type::succ;
};
template<> struct make_tuple_pack<0> {
using type = tuple_pack<>;
};
これで、タプルパックジェネレーターを適用して、実装関数に委任できます。
template<int N, int M, typename T> struct foo_impl {};
template<int N, int M, int... I> struct foo_impl<N, M, tuple_pack<I...>> {
static void foo() {
int arr[M] = { myFunction<N, M - I>()... };
}
};
template<int N, int M> void foo() {
foo_impl<N, M, typename make_tuple_pack<M>::type>::foo();
}
クラステンプレートの特殊化よりも関数パラメータの推論を好む場合、これは次のように書くこともできます。
template<int N, int M, int... I> void foo_impl(tuple_pack<I...>) {
int arr[M] = { myFunction<N, M - I>()... };
}
template<int N, int M> void foo() {
foo_impl<N, M>(typename make_tuple_pack<M>::type{});
}
配列サイズをint arr[M]
;として指定する必要がありました。それがパック拡張初期化子の標準で要求されているのか、それともgccのバグなのかわからない。いずれにせよ、それは大きな面倒ではありません。