5

I have the following C++11 code;

template<typename... T>
int g(T... t)
{
    return 0;
}

template<class... Args>
void f(Args... args)
{
    auto lm = [&, args...] { return g(args...); };
    lm();
}

int main()
{
    f(2, 5, 7);
}

I do believe that it's valid C++11, according to; Section 5.1.2.23 of the standard;

A capture followed by an ellipsis is a pack expansion (14.5.3). [ Example:

template<class... Args> void f(Args... args) {
    auto lm = [&, args...] { return g(args...); }; lm();
}

— end example ]

However while Clang++ compiles fine, G++ provides this error;

main.cpp: In function 'void f(Args ...)':
main.cpp:10:23: error: expected ',' before '...' token
     auto lm = [&, args...] { return g(args...); };
                   ^
main.cpp:10:23: error: expected identifier before '...' token
main.cpp:10:26: error: parameter packs not expanded with '...':
     auto lm = [&, args...] { return g(args...); };
                      ^
main.cpp:10:26: note:         'args'
main.cpp: In lambda function:
main.cpp:10:43: error: expansion pattern 'args' contains no argument packs
     auto lm = [&, args...] { return g(args...); };
                                       ^
main.cpp: In instantiation of 'struct f(Args ...) [with Args = {int, int, int}]::__lambda0':
main.cpp:10:49:   required from 'void f(Args ...) [with Args = {int, int, int}]'
main.cpp:16:14:   required from here
main.cpp:10:19: error: using invalid field 'f(Args ...)::__lambda0::__args'
     auto lm = [&, args...] { return g(args...); };
                   ^

So my question is simply, is this a compiler bug in G++?

Daniel Frey
  • 55,810
  • 13
  • 122
  • 180
Skeen
  • 4,614
  • 5
  • 41
  • 67

1 Answers1

3

It looks like support has not been implemented in GCC. Vice versa, you cannot have a lambda inside a pack expansion (to produce one lambda per pack argument). It seems the two features don't play together at all.

If you simply use [&] instead, then there is a more helpful error message:

sorry, unimplemented: use of ‘type_pack_expansion’ in template

Disclaimer: My copy of GCC was built in late July; I'm probably due for an upgrade.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Oh, lovely... Could I get the same behavior using std::function? - or will I have to change to Clang? – Skeen Sep 18 '13 at 11:48
  • @Skeen You could use pass the argument object pack to `std::bind`, with the first `bind` argument being a custom functor template type, with the template arguments being the type pack. `std::bind( my_func< Args ... >(), args ... )`. I think it should work for `my_func` being a "raw" function template, probably don't need a full-blown functor since bind takes care of state storage for you. To "capture by reference", use `std::ref( args ) ...` instead. – Potatoswatter Sep 18 '13 at 11:51