Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Variadic Templates pack expansions

In Andrei's talk on GoingNative 2012 he talks about Variadic Templates, and he explains at one point by way of the example underneath how the parameter pack expansions work. Being fairly new to this subject I found it fairly hard to follow how each case works, could anybody please explain how the expansion works in each function call of gun?

template<class... Ts> void fun(Ts... vs) {
    gun(A<Ts...>::hun(vs)...);
    gun(A<Ts...>::hun(vs...));
    gun(A<Ts>::hun(vs)...);
}
like image 727
Tony The Lion Avatar asked Feb 07 '12 19:02

Tony The Lion


People also ask

What is Variadic template in C++?

Variadic templates are class or function templates, that can take any variable(zero or more) number of arguments. In C++, templates can have a fixed number of parameters only that have to be specified at the time of declaration.

What is Pack expansion?

A pack expansion may designate the list of base classes in a class declaration. Typically, this also means that the constructor needs to use a pack expansion in the member initializer list to call the constructors of these bases: template<class... Mixins> class X : public Mixins...

What is the use of Variadic templates?

With the variadic templates feature, you can define class or function templates that have any number (including zero) of parameters. To achieve this goal, this feature introduces a kind of parameter called parameter pack to represent a list of zero or more parameters for templates.

What is a parameter pack C++?

Parameter packs (C++11) A parameter pack can be a type of parameter for templates. Unlike previous parameters, which can only bind to a single argument, a parameter pack can pack multiple parameters into a single parameter by placing an ellipsis to the left of the parameter name.


2 Answers

1.

   gun(A<Ts...>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(vs)...)
=> gun(A<T1, T2, …, Tn>::hun(v1),
       A<T1, T2, …, Tn>::hun(v2),
       …,
       A<T1, T2, …, Tn>::hun(vm))

2.

   gun(A<Ts...>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(vs...))
=> gun(A<T1, T2, …, Tn>::hun(v1, v2, …, vm))

This should be obvious.

3.

   gun(A<Ts>::hun(vs)...)
=> gun(A<T1>::hun(v1), A<T2>::hun(v2), …, A<Tn>::hun(vn))

(In this case the program won't compile if the lengths of Ts and vs differ)


The ... will expand a pattern (which includes any parameter packs) preceding it, meaning that, in foo(Ts, Us, Vs)..., each member of the list Ts, Us, Vs (enumerated in lock step) will be substituted into that pattern, and a comma separated list will be formed:

   foo(Ts, Us, Vs)...
=> foo(T1, U1, V1), foo(T2, U2, V2), …, foo(Tn, Un, Vn)

And if there are nested expansions, the innermost patterns will be expanded first. Therefore, in case 1, the pattern Ts will first be expanded into T1, T2, …, Tn. And then, the pattern preceding the outer ... is A<T1, T2, …, Tn>::fun(vs) — note that Ts has been expanded — so it will be expanded to A<T1, T2, …, Tn>::fun(v1), A<T1, T2, …, Tn>::fun(v2), …, A<T1, T2, …, Tn>::fun(vm) by substituting v1, v2, etc. into vs.

like image 169
kennytm Avatar answered Nov 07 '22 05:11

kennytm


KennyTM's answer is perfect. I just also like samples. But since his answer is abstract, I didn't feel like adding demos to his answer is the correct thing. So demos for his answer are here. I'm assuming his answer is right, I know nothing myself. (If you upvote this, upvote his too)

Obviously this is all psudocode just showing the expanded states.

void foo<void*,int,char,std::string>(nullptr, 32, '7', "BANANA") {
    //gun(A<Ts...>::hun(vs)...);
    gun(A<void*,int,char,std::string>::hun(nullptr)
       ,A<void*,int,char,std::string>::hun(32)
       ,A<void*,int,char,std::string>::hun('7')
       ,A<void*,int,char,std::string>::hun("BANANA")
       );
    //gun(A<Ts...>::hun(vs...));
    gun(A<void*,int,char,std::string>::hun(nullptr, 32, '7', "BANANA");
    //gun(A<Ts>::hun(vs)...);
    gun(A<void*>::hun(nullptr)
       ,A<int>::hun(32),
       ,A<char>::hun('7'),
       ,A<std::string>::hun("BANANA")
       );
}
like image 42
Mooing Duck Avatar answered Nov 07 '22 04:11

Mooing Duck