Consider the following code:
template<class T>
void f(const T& a, const T&b) { std::cout << "#1"; }
template<class ...T>
void f(T&& ...a) { std::cout << "#2"; }
int main() { f(0, 1); } // prints #2
I wonder why #2 is considered more specialized during overload resolution. The following are my reasoning for #1 being more specialized.
Following the rules for determining the partial ordering of function templates, we first perform deduction for transformed #1 against original template #2. From standard,
To produce the transformed template, for each type, non-type, or template template parameter (including template parameter packs (13.7.4) thereof) synthesize a unique type, value, or class template respectively and substitute it for each occurrence of that parameter in the function type of the template.
Suppose the unique synthesized type for transformed #1 is for T
is U
. Then during template argument deduction, for both arguments a
and b
, we have P = T&&
and A = const U&
. Following the deduction rules, we get T = const U&
for both arguments. The deduction succeeds, so #1 is at least as specialized as #2.
Now we perform deduction for transformed #2 against original template #1. According to this paragraph:
If the parameter-declaration corresponding to P_i is a function parameter pack, then the type of its declarator-id is compared with each remaining parameter type in the parameter-type-list of A. Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by the function parameter pack. During partial ordering, if A_i was originally a function parameter pack:
- if P does not contain a function parameter type corresponding to A_i then A_i is ignored;
- otherwise, if P_i is not a function parameter pack, template argument deduction fails.
In our case, our first argument A_1
was originally a function parameter pack, but P_1
is not a parameter pack. So template argument deduction fails, and #2 is not at least as specialized as #1. So #1 is more specialized.
Where does my reasoning break down?
That consideration would happen later.
The selection is already be done from "previous" criteria:
From Best_viable_function:
And then from Ranking_of_implicit_conversion_sequences