Variadic Templates - Understanding Parameter Package Extension
I am having a hard time understanding the parameter pack extension. What confuses me is that dots appear on the right side and dots appear on the left side. I ran into this which helped a little. Suppose I have the following two examples:
Example 1:
template <class ...A> --> line 1
int func(A... arg) --> line 2
{
return sizeof...(arg);
}
int main(void)
{
return func(1,2,3,4,5,6);
}
The post I mentioned above, I believe the difference is b / w ...A
and A...
is that the first has an extension on the left side and the second has a right side extension. I'm not sure what that means. Can anyone please clarify this with how something would look when expanded. The only thing I understand so far regarding the points on the right side are examples like
//Foo and bar are variadic parameter packs
Foo... => Foo1, Foo2, Foo3, etc
std::vector<Foo>... => std::vector<Foo1>, std::vector<Foo2>, std::vector<Foo3>, etc.
std::tuple<Foo...>(bar...) => std::tuple<Foo1, Foo2, Foo3, etc>(bar1, bar2, bar3, etc)
&bar... => &bar1, &bar2, &bar3, etc
Can anyone please clarify that dots are expanding on line 1 and line 2 and what is the difference between expanding the left side and expanding the right side?
source to share
There is no "left extension", there is only "extension to the right". When you typed:
template <class ...A>
int func(A... arg)
...
does not apply to A
. It helps to think of it like:
template <class... A>
As in, A
names the parameter package consisting of class
es. There is no extension on this line, it's just a parameter declaration for the function template func
.
Also, as TC points out , ...
in the argument list is grammatically bound to the argument name, not the type. This helps you understand particularly complex declarations such as:
template <typename... T>
void foo(T (*...fs)());
where fs
would be a (possibly empty) package of pointers to null functions.
As for the option pack extension, see my answer here for a list of examples of which option package extension is based on placement ...
. Short version: all packages in the expression immediately preceding ...
are expanded at the same time. All examples listed in your question are correct. I would add:
std::tuple<Foo...>(bar...) => std::tuple<Foo1, Foo2, Foo3, etc>(bar1, bar2, bar3, etc) std::tuple<Foo>(bar)... => std::tuple<Foo1>(bar1), std::tuple<Foo2>(bar2), ...
source to share