I have a program that looks like this:
class B {};
class A
{
template<typename T> int operator+(const T&) const { return 1; } // Function 1
};
template<typename T, typename P> int operator+(const T&, const P&) { return 2; } // Function 2
int main()
{
A a;
B b;
std::cout<<(a + b);
return 0;
}
In this scenario Function 2 will be called. But when I modify function 1 to be a free function instead of member function
template<typename T> int operator+(const A&, const T&) { return 1; } // Function 1
template<typename T, typename P> int operator+(const T&, const P&) { return 2; } // Function 2
Now Function 1 will be called, even though in both cases Function 1 is basically identical. What's the reasoning behind this? GCC complains about ambiguity according to ISO C++ standard but doesn't state the exact cause and compiles fine anyways. This case is unique to operators since they can be called in same way regardless if they are members or not.
Now Function 1 will be called, even though in both cases Function 1 is basically identical. What's the reasoning behind this?
Partial ordering of overloaded function templates is performed to select the best match here.
Informally "A is more specialized than B" means "A accepts fewer types than B".
Function 1 is more specialized than Function 2 because it accepts fewer types; it could accept only A
as its 1st operand, while Function 2 could accept any types.
For the same reason, in the 1st scenario the member Function 1 should be selected too; as clang does. This seems to be gcc's bug, see Bug 53499 and Bug 66914.