Reputation: 33693
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
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