Faisal Vali
Faisal Vali

Reputation: 33693

Does C++11 allow the following nested variadic expansion within and of a lambda?

Can anyone confirm for me that the following code (which includes nested expansions of a function parameter pack) is allowed in C++11 (I would certainly appreciate any references to the standard):

template<class ... VFTs> int variadic_fun(VFTs ... vfts) { 
  return sizeof ...(vfts); 
}


template<int ... Ns> struct IntPack {
  template<class ... MemTs> static int variadic_memfun(MemTs ... MemArgs) {
    return variadic_fun(([=]() {
      cout << "MemArgs = " <<  MemArgs << "\n";
      cout << "Ns = " << Ns;
      // Note the nested expansion of MemArgs here:
      cout << "variadic_fun(MemArgs...) = " << variadic_fun(MemArgs ...) << "\n";
      cout << "MemArgs[Ns] = " <<  MemArgs[Ns] << "\n";
      return 0;
    })()...);
  }  
};


int main() {
  IntPack<0, 1, 2>::variadic_memfun("123", "ABC", "XYZ");
}

Thanks!
P.S. Since someone asked below, this code works with my patch of clang that implements generic lambdas (Not yet standard C++, still just a proposal) - I have not tried it with any other compilers - and am not sure if it works with the latest clang trunk currently (it probably does) - I would certainly welcome any information on whether it compiles with any of the mainstream compilers that implement variadics and lambdas.

Upvotes: 4

Views: 308

Answers (1)

Richard Smith
Richard Smith

Reputation: 14158

Yes, this is valid, and Clang supports it.

$ clang++ your-example.cpp -std=c++11
$ ./a.out
MemArgs = 123
Ns = 0variadic_fun(MemArgs...) = 3
MemArgs[Ns] = 1
MemArgs = ABC
Ns = 1variadic_fun(MemArgs...) = 3
MemArgs[Ns] = B
MemArgs = XYZ
Ns = 2variadic_fun(MemArgs...) = 3
MemArgs[Ns] = Z

The relevant rule is [temp.variadic]p5:

An appearance of a name of a parameter pack that is not expanded is ill-formed.

That does not apply in this case, since

A parameter pack whose name appears within the pattern of a pack expansion is expanded by that pack expansion.

... and the uses of the pack within the lambda are within the pattern of the function argument pack expansion.

Upvotes: 6

Related Questions