5

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 ?

Community
  • 1
  • 1
James Franco
  • 4,516
  • 10
  • 38
  • 80
  • 2
    The spaces around the dots don't matter. So `class ...A` is equivalent to `class... A`, and `A... arg` is equivalent to `A ...arg`. Only `sizeof...` cannot have spaces. – dyp Jul 27 '15 at 17:53
  • @dyp Are you sure about `sizeof...`? – T.C. Jul 27 '15 at 17:56
  • @T.C. Not entirely. There are some hints in the standard, like *"The `sizeof...` operator"*.. – dyp Jul 27 '15 at 18:04
  • @dyp Well, I can find no `sizeof...` token, so I don't see why there can't be spaces. – T.C. Jul 27 '15 at 18:04
  • 1
    @T.C. Ok, I retract that statement about `sizeof`. There are spaces in the BNFs, and both g++ and clang++ accept `sizeof ...` – dyp Jul 27 '15 at 18:07
  • possible duplicate of [What are the rules for the "..." token in the context of variadic template?](http://stackoverflow.com/questions/17652412/what-are-the-rules-for-the-token-in-the-context-of-variadic-template) – Walter Jul 27 '15 at 18:21

1 Answers1

4

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 classes. 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), ...
Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977
  • 1
    I would say that `class ...A` is about *contraction*, not expansion. Turning a group of types into one pack. Whereas `A...` is about expansion, expanding one pack into a group of types. e.g. if you explicitly call `func(1,'1',1.0)` then you a *building* a pack, not *expanding* it. – Aaron McDaid Jul 27 '15 at 18:01
  • 3
    It's useful to know that in `A ...args`, the `...` binds to `args` as a matter of grammar, though. Some crazier declarators don't make much sense unless you know that. – T.C. Jul 27 '15 at 18:08
  • 1
    @T.C. Updated, with crazy declarator. – Barry Jul 27 '15 at 18:20