Let's first introduce a helper type that represents a parameter pack:
template<typename... T> struct Pack { };
Now, here's the function with the weird behaviour:
template<typename... TT, typename T>
void f(Pack<TT...>, Pack<T>, std::type_identity_t<TT>..., std::type_identity_t<T>);
std::type_identity_t is used here to disable deduction from the last two parameters in case that would introduce any ambiguity.
First, I tried to call it like so:
f(Pack<int>{}, Pack<int>{}, 5, 5);
GCC raises an error and gives the following explanation:
<source>:12:6: note: candidate expects 3 arguments, 4 provided
12 | f(Pack<int>{}, Pack<int>{}, 5, 5);
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
That's not the kind of error I expected, I assumed that deduction would result in T = int and TT... = int. But okay, let's do what the note says and provide one less argument:
f(Pack<int>{}, Pack<int>{}, 5);
It still gives an error, but this time it's:
<source>:12:6: error: too few arguments to function 'void f(Pack<TT ...>, Pack<T>, std::type_identity_t<TT>..., std::type_identity_t<T>) [with TT = {int}; T = int; std::type_identity_t<T> = int]'
10 | f(Pack<int>{}, Pack<int>{}, 5);
| ~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Now it's too few of them. Also notice that this error message confirms my assumption about the deduced T and TT....
At this point I switched to Clang to see whether it'd compile this code, but both of the above calls to f (with 3 and 4 arguments) result in the same error, with the note:
<source>:8:6: note: candidate template ignored: deduced packs of different lengths for parameter 'TT' (<int> vs. <>)
void f(Pack<TT...>, Pack<T>, std::type_identity_t<TT>..., std::type_identity_t<T>);
^
I also tried compiling the code with MSVC, and it did compile without errors.
What is going on? Is there something that makes this code invalid? Is it a compiler bug, due to the strange error messages?