clang correctly rejects as ambiguous:
template<class T> int f(T&, int); 1
template<class T, class U> int f(T const&, U); 2
int g(int const& i) { return f(i, 0); }
However if the order of template parameters in (2) is swapped:
template<class T> int f(T&, int); 1
template<class U, class T> int f(T const&, U); 2'
int g(int const& i) { return f(i, 0); }
clang incorrectly accepts, calling (1).
All versions tested up to current trunk incorrectly accept; 3.6 and older also incorrectly accept the first case.
gcc correctly rejects both cases since 4.5, incorrectly accepting in earlier versions.
icc 13 onwards correctly rejects.
MSVC correctly rejects (although it has other bugs in this area).
The problem appears to be that DeduceTemplateArgumentsByTypeMatch incorrectly believes that P and A are distinct; P is type-parameter-0-1 whereas A is type-parameter-0-0.
I believe this can be fixed simply by removing the hasSameUnqualifiedType check, since if the types are dissimilar the call would fail later anyway,