template <typename T> void f(T&) {}
template <typename T> void f(T&&) {}
int main()
{
int x;
f(x); //ambiguous
}
Why is this call ambiguous? The first template specialization is f<int>(int&), and the second is f<int&>(int&). As the parameters are the same, the function template, which is more specialzed according to the partial ordering rules, is better. Then according to Standard 14.8.2.4/9
If, for a given type, deduction succeeds in both directions (i.e., the types are identical after the transformations above) and both P and A were reference types (before being replaced with the type referred to above):
— if the type from the argument template was an lvalue reference and the type from the parameter template was not, the argument type is considered to be more specialized than the other; …
The first template has T& and the second has T&&, so the first should be more specialized. What is wrong here?
Edit:
This code is tested in g++ 4.6.1 and VC++ 2010 Express, both give the ambiguous error.
Your interpretation of the standard appears to be correct.
In #1,
Tis successfully deduced asint, and in #2,Tis successfully deduced asint&, so partial ordering is performed to select the function to call. During partial ordering for the callf(x), the types of the first (only, in this case) argument will be ordered ([temp.deduct.partial]/3 bullet 1). During deduction in both directions, typePwill beT, and typeAwill be a synthesized type representingT([temp.deduct.partial]/5), so deduction succeeds in both directions.As you observed, [temp.deduct.partial]/9 then applies, and says that #1’s first argument is more specialized. Therefore, by [temp.deduct.partial]/10, #1 is selected as the most-specialized template and its specialization is the result of overload resolution.
You didn’t mention which compiler you are using. I assume it’s g++ — this appears to be a bug in that compiler (I’ve tested versions between 4.4.3 and 4.7, and they all reject this code). clang accepts your code, and calls the
f(T &)overload as you expected.