Consider the code below. Although both overloads of fun accept pointers, passing nullptr to fun does not result in any compilation error. Whereas, the very similar function bun fails to compile. When I print the the types of the argument i using typeid(i).name() (after modifying the code just to get this printed) I get the same type, simply int*. What is the rule that resolves the ambiguity in fun case, but fails for bun? Thanks in advance!
#include <iostream>
struct Foo {
int sth;
};
template< class U>
void fun(decltype(U::sth)* i){
std::cout << "1" << std::endl;
}
template< class U>
void fun(U* i){
std::cout << "2" << std::endl;
}
void bun(decltype(Foo::sth)* i){
std::cout << "3" << std::endl;
}
void bun(Foo* i){
std::cout << "4" << std::endl;
}
int main ( )
{
fun<Foo>(nullptr);
// bun(nullptr); --> call of overloaded 'bun(std::nullptr_t)' is ambiguous
return 0;
}
-----------------------
output : 1
Well, in fact, GCC accepts your code, but Clang does not. So it is not, at first, obvious whether the call is ambiguous.
You ask what rule resolves the ambiguity in the
funcase; GCC evidently thinks that there is such a rule. I imagine the rule that GCC is applying is the rule [over.match.best]/1.7 that prefers a more specialized function template over a less specialized one.The procedure for determining which function template is more specialized than the other is described in [temp.func.order] and is explained thoroughly in this SO answer. However, you will notice that when attempting to apply this procedure to the two overloads of
funas in this question, we run into the problem that the unique synthesized type that needs to be substituted forUin the first overload would need to have a member namedsth, and the nature of this member is not specified, and although it may be clear to a human that deduction in the secondfunoverload must succeed regardless of whatsth's type is, the compiler may not be able to prove it.This is CWG 1157. As this issue is still open with no proposed resolution, I have no insight into whether WG21 intends for this overload resolution to succeed or not.