【问题标题】:How do templates avoid infinite recursion?模板如何避免无限递归?
【发布时间】:2020-11-10 07:06:49
【问题描述】:

我目前在 SDL2 上关注 this tutorial,并且遇到了模板,这些模板对我来说是全新的。

template<typename T, typename... Args>
void cleanup(T *t, Args&&... args){
    cleanup(t);
    cleanup(std::forward<Args>(args)...);
}

template<> inline void cleanup<SDL_Window>(SDL_Window *window){
    ...
}
...

我不明白如何在cleanup() 函数中调用cleanup() 不仅会创建无限递归循环,而是调用下面的专用模板函数之一。此外,我无法为a 调用forward() 而为b 调用没有多大意义,就我所收集到的而言,forward() 应该可以解决在使用左值和右值调用cleanup() 时出现的任何问题.

【问题讨论】:

  • 好吧,cleanup(T *t, Args&amp;&amp;... args) 的参数与cleanup&lt;SDL_Window&gt;(SDL_Window *window) 不同,前者采用T 类型的参数和typename... Args 的可变数量的参数。请注意,typename... Args 仍然需要至少一个参数,因此您的模板清理函数和已解析的显式函数之间没有歧义。
  • 模板类型在编译时被转换为特定的函数/类。对于可变参数模板,编写“递归”是常见的做法。你可以阅读this tutorial 的第一部分来弄清楚为什么它在技术上不是递归
  • @h0r53: typename... Args 不需要至少一个参数,它可以匹配零。但由于重载规则,这是一个比其他任何事情都更糟糕的匹配。

标签: c++ templates recursion variadic-templates rvalue


【解决方案1】:
cleanup(T *a, Vars&&... b)

如果您将n vars 传递给此函数,则第一个将转到主体中的第一个函数(结束。请注意,没有内部调用)。

其余的 n-1 将转到正文中的第二个函数,这将再次调用一个函数,但使用 n-1 变量。

这个过程会一直持续到只有两个参数,然后第一次和第二次调用都将使用第二个函数,因为它是最佳匹配。

因此这不是无穷无尽的功能。

【讨论】:

  • “cleanup() 函数中的清理函数不只是创建无限递归循环,而是调用下面的专用模板函数之一。”我认为这里的关键部分是运算符重载规则,使所有其他方法更好地匹配 1 参数形式。
  • Re:“第二个不会被调用,因为参数包是空的”:我不认为这是一个正确的解释。空参数包是有效的——但在这种情况下,它会导致编译错误而不是无限递归,因为没有零参数cleanup()。 (如果你要创建一个零参数cleanup(),然后写cleanup(foo),其中foo 有某种没有专门化的类型,那么你确实会得到无限递归!)
猜你喜欢
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 2013-05-25
  • 2014-09-10
  • 1970-01-01
  • 2012-10-26
  • 2021-07-31
相关资源
最近更新 更多