这个可变参数模板是如何工作的?

6

我在查看这个SO问题时,无法理解答案是如何工作的。以下是其中一个答案中代码的副本:

template<int ...> struct seq {};

// How does this line work?
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };

double foo(int x, float y, double z)
{
    return x + y + z;
}

template <typename ...Args>
struct save_it_for_later
{
  std::tuple<Args...> params;
  double (*func)(Args...);

  double delayed_dispatch()
  {
     return callFunc(typename gens<sizeof...(Args)>::type());
  }

  template<int ...S>
  double callFunc(seq<S...>)
  {
     return func(std::get<S>(params) ...);
  }
};

int main(void)
{
  std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
  save_it_for_later<int,float, double> saved = {t, foo};
  cout << saved.delayed_dispatch() << endl;
}

我不理解的部分是这个:
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

在这个例子中,假设sizeof..(Args)3,则代码return callFunc(typename gens<sizeof...(Args)>::type());中的gens<sizeof...(Args)>::type()将被调用。
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

变成

template<3, {}> struct gens : gens<3-1, 3-1, {}> {};

这句话是否正确,如果是,接下来会发生什么?
1个回答

7

让我们手动写出递归:

gens<3> : gens<2, 2>
gens<3> : gens<2, 2> : gens<1, 1, 2>
gens<3> : gens<2, 2> : gens<1, 1, 2> : gens<0, 0, 1, 2>

递归停止是因为针对0的部分特化:
struct gens<0, S...>{ typedef seq<S...> type; }; 

// first 0 consumed by the partial specialization
//= 0,1,2
struct gens<0, 0, 1, 2> { 
    typedef seq<0, 1, 2> type;
}

谢谢。以那种方式使用递归真的让我感到困惑。 - Jesse Good
谢谢,我也对这部分感到非常困惑。 - Zeks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接