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?
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.
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.
variadic (not comparable) (computing, mathematics, linguistics) Taking a variable number of arguments; especially, taking arbitrarily many arguments.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With