理解可变参数模板函数

时间:2015-06-19 01:34:03

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

我是可变参数模板的新手,最近遇到了它。我想我还没有完全理解它在后台如何运作。我试着写一个可变函数 min ,它返回最小的参数。

以下是代码:

#include <iostream>

template<typename T>
T min(T v) {
    std::cout << "Base func:     " << __PRETTY_FUNCTION__ << "\n";
    return v;
}

template<typename T, typename... Args>
T min(T first, Args... args) {
    std::cout << "Variadic func: " << __PRETTY_FUNCTION__ << "\n";
    return first < min(args...) ? first : min(args...);
}

int main(){

    std::cout << min(3,2,1,0) << std::endl;

    return 0;
}

我使用__PRETTY_FUNCTION__来获取函数实例化的更多细节,这里是输出:

Variadic func: T min(T, Args ...) [with T = int; Args = {int, int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func:     T min(T) [with T = int]
Base func:     T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func:     T min(T) [with T = int]
Base func:     T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int, int}]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func:     T min(T) [with T = int]
Base func:     T min(T) [with T = int]
Variadic func: T min(T, Args ...) [with T = int; Args = {int}]
Base func:     T min(T) [with T = int]
Base func:     T min(T) [with T = int]
0

代码返回正确的输出,但我仍然模糊调用函数的方式。是否所有论据都相互比较?例如。 3将与2,1,0进行比较,2将与1,0进行比较,1将与0进行比较?如果有人可以对确切的事情给出一个可靠的推理,那将会很棒吗?

由于

2 个答案:

答案 0 :(得分:3)

调用层次结构如下。可变函数调用“少一个”函数两次,因为first < min(args...) ? first : min(args...);调用它一次以将其与first(标有// compare)进行比较,如果比较为{{1}则第二次调用false }(标有// value)。

min(3,2,1,0) // compare
  -> min(2,1,0) // compare
    -> min(1,0) // compare
      ->min(0) // compare
      ->min(0) // value
    -> min(1,0) // value
      ->min(0) // compare
      ->min(0) // value
  -> min(2,1,0) // value
    -> min(1,0) // compare
      ->min(0) // compare
      ->min(0) // value
    -> min(1,0) // value
      ->min(0) // compare
      ->min(0) // value

我希望这会让你更具可读性。

答案 1 :(得分:1)

如果您展开模板调用并通过缓存递归值的结果来修复双递归,它应该看起来像这样

这并不意味着是c ++,c ++是问题中的模板代码,这只是传递3个args的手动调试

min (a, b, c)
  First = a;
  Tailmin = min (b, c);
  if (first < Tailmin)
     return first;
  return Tailmin;

min (b, c)
  First = b;
  Tailmin = min (c);
  if (first < Tailmin)
     return first;
  return Tailmin;

min (c)
// base stops recursion
   return c