Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does this variadic template work?

I was looking at this SO question and I couldn't understand how the answer worked. I will post a copy of code in one of the answers for reference:

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;
}

The part I don't understand is this:

template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

In the example at return callFunc(typename gens<sizeof...(Args)>::type()); I'm assuming that sizeof..(Args) would be 3. So,

template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};

becomes

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

Is this correct, and if so, what happens from there?

like image 793
Jesse Good Avatar asked Mar 16 '12 03:03

Jesse Good


People also ask

How do you write a variadic function in C++?

Variadic functions are functions (e.g. std::printf) which take a variable number of arguments. To declare a variadic function, an ellipsis appears after the list of parameters, e.g. int printf(const char* format...);, which may be preceded by an optional comma.

What is variadic Python?

variadic is a Python (2.7+ and 3.4+) function decorator to write variadic functions accepting a mix of arguments and iterables of those arguments. Oh, and they keep their argspec, so tools doing introspection (Sphinx doc, IDEs, etc.) will work well.

What means variadic?

variadic (not comparable) (computing, mathematics, linguistics) Taking a variable number of arguments; especially, taking arbitrarily many arguments.


1 Answers

Let's write down the recursion manually:

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>

The recursion stops because of the partial specialization for 0:

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

// first 0 consumed by the partial specialization
// S = 0,1,2
struct gens<0, 0, 1, 2> { 
    typedef seq<0, 1, 2> type;
}
like image 117
J.N. Avatar answered Sep 30 '22 07:09

J.N.