递归模板解释C

新手上路,请多包涵
template<typename... ArgTypes>
int add(ArgTypes... args);

template<typename T, typename... ArgTypes>
int add(T t, ArgTypes... args)
{
    int sum = 0;
    return t + add(args...);
}
template<> int add() {
    return 0;
}

如何添加更多的运算,如乘法和减法? template<> int add() 是什么意思?

谁能详细解释这个递归模板是如何工作的?

UPD:谢谢你们关于减法,是的,减法不是可交换的,所以它并不适合这种递归模板。

UPD2:添加了一个调用堆栈作为社区的参考 可变参数模板的调用堆栈

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

阅读 422
2 个回答

它是很常见的递归 可变参数模板。这个想法是我们使用递归

f(x0, x1, ..., xn) = f(f(x0, x1, ..., xn-1), xn) (1) ,

在您的样本中

add(x0, x1, ..., xn) = add(x0, x1, ..., xn-1) + xn

可变参数模板提供了创建这种结构的简单而有用的方法。

首先,定义模板的通用签名(没有实现,因为我们从不使用通用形式)

 template<typename... ArgTypes>
int add(ArgTypes... args);

现在将模板函数专门用于具有至少一个参数的情况。我们使用递归,它提取第一个参数并递归调用自身,参数数量减少一个。

 template<typename T, typename... ArgTypes>
int add(T t, ArgTypes... args)
{
    int sum = 0;
    return t + add(args...); // recursive call without first arg
}

为了停止递归,我们对空模板参数列表使用模板特化(我们在最后一步添加 0 )。

 template<> int add() {
    return 0;
}

For multiplication you need just change + by * , becuse general recursive form (1) is identical in both case, and change return 0 to return 1 (在最后一步乘以 1 )。

在减法的情况下,递归 (1) 的一般形式是不可用的,因为 a-b != b-a 会产生歧义。还有除法和其他非交换操作。您必须明确操作顺序。

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

这是我的解释尝试。

首先:

 template<typename... ArgTypes>
int add(ArgTypes... args);

这是起点。它说“存在一个名为 add 的函数,它接受 零个或多个 通用参数”。它不包含实现,所以它本身就相当于向编译器承诺这样一个函数将会存在。

然后我们有:

 template<typename T, typename... ArgTypes>
int add(T t, ArgTypes... args)
{
    int sum = 0; // This line isn't doing anything!
    return t + add(args...);
}

这表示“这是一个名为 add 的函数,它接受 一个或多个 通用参数”。它包括一个实现。该实现的一部分递归调用 add(args...) 除了第一个参数(即零个或多个)之外的所有参数。上面的第一个声明告诉我们这是存在的。

如果 args 中至少有一个参数,那么这个递归调用最终将再次调用完全相同的函数。但是当 args 包含零参数时会发生什么?我们需要函数的一个版本(特化)来处理这种情况,这是我们的第二个定义中唯一没有处理的情况。这就是第三个声明的来源:

 template<> int add() {
    return 0;
}

这定义了一个名为 add 的函数,它需要 争论。

所以,总结一下:

  1. 第二个声明定义了一个接受 一个或多个 参数的函数
  2. 第三个声明定义了一个接受 参数的函数
  3. 总之,这意味着我们有一个函数接受 零个或多个 参数,正如第一个声明所声明的那样。

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

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