10

the following code snippet won't compile under gcc4.6.1:

template <typename... TS>
void do_stuff(TS... ts)
{
  auto f = [](TS... things) { };
}

It throws an error stating that the pack things was not expanded. The following code does compile however:

template <typename... TS>
void do_stuff(TS... ts)
{
  auto f = [](TS... things...) { };
}

Notice the extra unpacking operator after things inside the parameter list. I've never seen a situation where a variadic pack had to be expanded during its declaration. So my question to you kind folks is:

Is this legal C++0x syntax (the snippet that compiles) or is it just a quirk with GCC when it comes to dealing with variadic types?

Cœur
  • 37,241
  • 25
  • 195
  • 267
bstamour
  • 7,746
  • 1
  • 26
  • 39
  • 2
    That isn't "capturing", capturing happens inside the `[]` brackets. You're just specifying an argument list. (But nice question!) – Kerrek SB Jul 26 '11 at 14:27
  • Thanks, I edited it to make more sense. I knew it wasn't capturing in the variable sense, but it seems like it's an issue with how the lambda "captures" that type TS... – bstamour Jul 26 '11 at 14:42
  • Ah, I think I found the answer, which is "no": http://stackoverflow.com/questions/3575901/can-lambda-functions-be-templated – Kerrek SB Jul 26 '11 at 14:43
  • But the lambda function itself is not templated. When it comes time for the lambda expression to be evaluated, those types will be well defined. – bstamour Jul 26 '11 at 14:48
  • Hm, right, disregard that comment. Actually, it seems that you can also say `doStuff(TS... ts...)`. I don't know if `(TS... ts)` is a permissible shorthand for member function declarations... – Kerrek SB Jul 26 '11 at 14:49

1 Answers1

6

Two things:

  • Yes, GCC is wrong to reject [](TS... things) { }. It's possible that it hasn't been implemented yet.
  • What you declared by [](TS ... things...) { } is equivalent to [](TS... things, ...). In C++ (not in C), you can leave off the comma before the C-style variadic ellipsis. So instead of doing void printf(char const *fmt, ...) you can declare void printf(char const *fmt...). That's what happens in your lambda. The first ellipsis is the parameter pack unpacking, and the second ellipsis is the C-style variadic ellipsis.
Johannes Schaub - litb
  • 496,577
  • 130
  • 894
  • 1,212
  • That's very good to know, but how come `auto m = [](Args... p...) { printf("%d%d\n", p...); };` actually works in GCC 4.6 if I call `m(1,2);` and prints out `12`? – Kerrek SB Jul 26 '11 at 22:05
  • @Kerrek It's hard to second-guess. `-std=c++0x` is called *experimental* support for the next C++ Standard after all. – Luc Danton Jul 27 '11 at 06:39