Effective C++ Note 25: Avoid overloading on a pointer and a numberical type
What will happen here?
void f(int x){cout<<"int"<<endl;};
void f(string * x){cout<<"string"<<endl;};
void main(){
f(NULL);
}
Most people use NULL to indicate a pointer. But as we all know, NULL is defined to be 0. So the code above will generate an output of "int" instead of the expected "string".
And with the following code, we get an "ambiguous function call" error.
void f(long x){cout<<"long"<<endl;};
void f(string * x){cout<<"string"<<endl;};
void main(){
f(NULL);
}
Why is that? That is because NULL can be converted to a long integer, or a pointer to string, and the compiler just can't decide what to do.
So the wise thing to do is avoid overloading on a pointer and a numberical type.
But what if I really want to do that? Well, you can redefine NULL as follows:
const // this is a const object...
class {
public:
template<class T> // convertible to any type
operator T*() const // of null non-member
{ return 0; } // pointer...
template<class C, class T> // or any type of null
operator T C::*() const // member pointer...
{ return 0; }
private:
void operator&() const; // whose address can't be
// taken (see Item 27)...
} NULL; // and whose name is NULL
This code seems hard to understand, does it? And you must make sure you use NULL rather than 0 when you want to call f(string *). If you try f(0), f(int) will still be the function called.