The program is ill-formed and gcc and clang are wrong in accepting the code. You can also confirm this by slightly modifying your code to as shown below. There is also an old gcc bug for this.
Basically, in case of function templates(in the modifed program shown below) multiple template parameter packs are permitted, as long as each template parameter following a template parameter pack has either a default value or it can be deduced. But since neither of these requirements is satisfied for T2
and T3
(as they cannot be unambiguously deduced and cannot have default arguments), the program is ill-formed.
The exact same reasoning applies to your given example as foo
(in your original example) is a generic function(aka abbreviated function template).
GCC and Clang shows the same incorrect behavior for the following modified program: Demo
template<typename... T1, typename... T2, typename... T3>
void foo(T1&&...args1, T2&&... args2, T3&&... args3) {
std::cout << "args1:\n", ((std::cout << args1 << " "), ...);
std::cout << "args2:\n", ((std::cout << args2 << " "), ...);
std::cout << "args3:\n", ((std::cout << args3 << " "), ...);
}
int main(int argc, char** argv)
{
foo(1,2,3,4,5,6); //gcc and clang compiles this while msvc correctly rejects this
}
Here is the gcc bug:
GCC accepts invalid program involving multiple template parameter packs
Here is the clang bug:
Clang accepts invalid program involving multiple template parameter packs
The same can also be seen from temp.param:
A template parameter pack of a function template shall not be followed by another template parameter unless that template parameter can be deduced from the parameter-type-list ([dcl.fct]) of the function template or has a default argument ([temp.deduct]).
// U can be neither deduced from the parameter-type-list nor specified
template<class... T, class... U> void f() { } // error
(emphasis mine)