Take a look at these two overloaded function templates:
template <class T>
int foo(T& x) { // #1
return 1;
}
template <class T>
int foo(T&& x) { // #2
return 2;
}
I call foo
in the following way:
int i;
foo(i); // calls #1
And overload #1 is unambiguously chosen: https://gcc.godbolt.org/z/zchK1zxMW
This might seem like a proper behavior, but I cannot understand why it happens (and I actually had code where this was not what I expected).
From Overload resolution:
If any candidate is a function template, its specializations are generated using template argument deduction, and such specializations are treated just like non-template functions except where specified otherwise in the tie-breaker rules.
OK, let's generate specializations. For #1 it's easy, it becomes int foo(int& x)
. For #2 special deduction rules apply, since it is a forwarding reference. i
is an lvalue, thus T
is deduced as int&
and T&&
becomes int& &&
, which after reference collapsing becomes just int&
, yielding the result int foo(int& x)
. Which is exactly the same as for #1!
So I'd expect to see an ambiguous call, which does not happen. Could anyone please explain why? What tie-breaker is used to pick the best viable function here?
See also the related discussion in Slack, which has some thoughts.