递归地构造一个无符号int的变量模板

Construct a variadic template of unsigned int recursively

本文关键字:int 无符号 变量 一个 递归      更新时间:2023-10-16

我在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>

如何做到这一点(当然如果可能的话)?

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

// 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中的一个错误;不管怎样都没什么大麻烦。