如何编写可变参数模板递归函数?

新手上路,请多包涵

我正在尝试编写一个可变参数模板 constexpr 计算给定模板参数总和的函数。这是我的代码:

 template<int First, int... Rest>
constexpr int f()
{
    return First + f<Rest...>();
}

template<int First>
constexpr int f()
{
    return First;
}

int main()
{
    f<1, 2, 3>();
    return 0;
}

不幸的是,在尝试解析 f<3,>() 调用时,它不会编译报告错误消息 error C2668: 'f': ambiguous call to overloaded function

我还尝试更改我的递归基本案例以接受 0 个模板参数而不是 1:

 template<>
constexpr int f()
{
    return 0;
}

但是此代码也无法编译(消息 error C2912: explicit specialization 'int f(void)' is not a specialization of a function template )。

我可以提取第一个和第二个模板参数以使其编译和工作,如下所示:

 template<int First, int Second, int... Rest>
constexpr int f()
{
    return First + f<Second, Rest...>();
}

但这似乎不是最好的选择。所以,问题是:如何以优雅的方式编写这个计算?

UP :我也尝试将其编写为单个函数:

 template<int First, int... Rest>
constexpr int f()
{
    return sizeof...(Rest) == 0 ? First : (First + f<Rest...>());
}

这也不起作用: error C2672: 'f': no matching overloaded function found

原文由 alexeykuzmin0 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 438
2 个回答

你的基本情况是错误的。您需要一个空列表的案例,但正如编译器所建议的那样,您的第二次尝试不是有效的模板特化。为零参数定义有效实例化的一种方法是创建一个接受空列表的重载

template<class none = void>
constexpr int f()
{
    return 0;
}
template<int First, int... Rest>
constexpr int f()
{
    return First + f<Rest...>();
}
int main()
{
    f<1, 2, 3>();
    return 0;
}


编辑:为了完整起见,也是我的第一个答案,@alexeykuzmin0 通过添加条件来修复:

 template<int First=0, int... Rest>
constexpr int f()
{
    return sizeof...(Rest)==0 ? First : First + f<Rest...>();
}

原文由 example 发布,翻译遵循 CC BY-SA 3.0 许可协议

我发现将代码从模板参数移动到函数参数通常更容易:

 constexpr int sum() { return 0; }

template <class T, class... Ts>
constexpr int sum(T value, Ts... rest) {
    return value + sum(rest...);
}

如果你真的想要它们作为模板参数,你可以让你的 f 只需调用 sum 通过将它们向下移动:

 template <int... Is>
constexpr int f() {
    return sum(Is...);
}

它是 constexpr ,所以只需使用 int s 就可以了。

原文由 Barry 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题