Consider the following code:
#include <iostream>
using namespace std;
void fun(const char* s){
if (s == nullptr) {
puts("const char* nullptr");
} else {
printf("%s\n", s);
}
}
template <typename T>
void fun(T* p){
printf("%p\n", p);
}
int main() {
int a;
fun("abc"); // Resolves to fun(const char*)
fun(&a); // Specializes the template to int*
fun(nullptr); // Uses fun(const char*)??
fun(NULL); // Same as above
}
I'm surprised that g++ 7.2.0
does not throw an error about ambiguous overload resolution, as I think nullptr
and NULL
could fit into any pointer type, including fun(int*)
specialized from the template, provided there isn't an overload specialized for std::nullptr_t
.
Why does fun(nullptr)
and fun(NULL)
resolves directly to fun(const char *)
?
std::nullptr_t
is not a pointer, so it will not pattern-match T*
in your function template.
As counter-intuitive as this is, the following assert will not fire:
static_assert(std::is_pointer<std::nullptr_t>() == false);
As for NULL
, it is an implementation-defined macro. If cppreference is to be believed, it's either an integer literal with value of zero (so not a pointer), or a prvalue of type std::nullptr_t
, which is explained above. It is not a void*
pointer.