Reputation: 4706
I am having a hard time understanding parameter pack expansion. The thing that confuses me are when dots appear on the right side and when dots appear on the left side. I came across this post 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 mentions that the difference b/w ...A
and A...
is that the first one does Left side expansion and the second one does right side expansion. I am not sure what that means. Could anyone please clarify this with how something would look like when expanded. The only thing I understand so far regarding dots on the right hand side are the examples such as this
//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
could any one please clarify what the dots expand to in line 1 and line 2 and what is the difference between left side expansion and right side expansion ?
Upvotes: 6
Views: 1808
Reputation: 303027
There is no "left-side expansion", there is only "right-side expansion." When you typed:
template <class ...A>
int func(A... arg)
The ...
does not apply to the A
. It helps to think of it as:
template <class... A>
As in, A
names a parameter-pack consisting of class
es. There is no expansion going on in that line - it's just declaring what the parameters are for the function template func
.
Furthermore, as T.C. points out, the ...
in the argument list grammatically binds to the argument name not its type. This helps make sense of particularly complicated declarations such as:
template <typename... T>
void foo(T (*...fs)());
where fs
would be a (possibly-empty) pack of pointers to nullary functions.
As for parameter pack expansion, see my answer here for a list of examples of what parameter expansion does based on the ...
placement. The short version is: all the packs in the expression immediately preceding the ...
are expanded concurrently. All of the examples you listed in your question are correct. I would additionally 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), ...
Upvotes: 5