Clang deduces Ts from two conflicting sources: type_list<Ts...> and Ts&&.... Because you call foo with type_list<int>{}, Ts is first deduced as {int}. However, because the last argument Ts_&&... has the type of a parameter pack, it catches all that it can; in this case, the last two arguments (while T_&&t is passed the 5), which deduces Ts_ as {double, int} (and T_ as int). This leaves Ts with no argument, so it's deduced as {}.
Hence Clang's error message: Ts is deduced both as {} and {int} (the (<int> vs. <>) in the error message).
Note that GCC does things differently:
error: too few arguments to function 'auto foo(type_list, Ts&& ..., T_&&, Ts_&& ...) [with Ts = {int}; T_ = int; Ts_ = {double, int}]'
It tries to keep Ts deduced as {int} but still deduces Ts_ as {double, int}, and so there is no way to give the correct number of arguments.
To explain a bit further, consider the following:
template <class ... Ts>
struct type_list{};
template <class ... Ts>
auto foo(type_list<Ts...>, Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Clang correctly calls this out because the two deductions are conflicting:
note: candidate template ignored: deduced conflicting types for parameter 'Ts' (<int> vs. <int, double, int>)
Trouble is, you can't catch 2 of the arguments with another parameter pack, because it will either catch everything if placed after (which is your case), or nothing if placed before:
template <class ... Ts>
struct type_list{};
template <class... Ts, class... Ts_>
auto foo(type_list<Ts...>, Ts_..., Ts...) {
return sizeof...(Ts);
}
int main() {
std::cerr << foo(type_list<int>{}, 5, 5.0, 3);
}
Here, Clang produces the same error message because Ts is still deduced as both {int} from the type_list, and {int, double, int} by catching all the remaining arguments.
I think your only choices are to somehow deal with tuples or be more explicit with the call: foo<int>(type_list<int>{}, 5, 5.0, 3) (and you can probably remove the type_list in this case). That way, Ts isn't deduced anymore: you explicitly make it {int}.