以递归方式构造unsigned int的可变参数模板

时间:2012-09-05 14:41:54

标签: c++ templates c++11 metaprogramming variadic-templates

我在C ++ 2011代码中需要一件棘手的事情。 目前,我有一个这样的元功能:

template<unsigned int N, unsigned int M> 
static constexpr unsigned int myFunction()

此功能可以根据NM生成数字。

我想用输入NM编写一个元函数,它将通过递减M递归构造一个可变参数模板。例如,通过使用M = 3调用此函数,它将构造一个名为List的可变参数模板,其等于:

List... = myFunction<N, 3>, myFunction<N, 2>, myFunction<N, 1>, myFunction<N, 0>

如何做到(如果可能的话)?

1 个答案:

答案 0 :(得分:4)

使用现有的元组包生成器可能最简单:

// 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<>;
};

现在我们可以应用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中的错误;无论哪种方式都没有什么大麻烦。