C++ Type Casting – Should Comparisons Be Cast to NULL or nullptr?

ctype casting

Let's say I have a C++ function that looks like this:

bool Foo(Bar* b)
{
    if(b == nullptr) {
        return false; 
    }
    // Do stuff
    return true;
}

Let's further say that, because of limitations with some of the tools I have that don't support any standards newer than C++03, I have this code in a header:

#if __cplusplus <= 199711L
    #define nullptr (0)
    #include <stdint.h>
#else
    #include <cstdint>
#endif // End if C++03

My compiler will build this without warning or error. I know I don't have to cast nullptr but is there a compelling reason that I should do it? That is, is there the potential for some bug to creep in relative to to Foo() that using if (b == static_cast<Bar*>(nullptr)) would have avoided and that the compiler wouldn't have warned me about (in either C++03 or C++11 or later)?

My reasons for avoiding the cast would be:

  1. Adding the cast to every use of nullptr seems like it would make the code more cluttered/harder to read.
  2. I haven't seen much (if any) code that does so.

Number 2 isn't a good reason in and of itself, so I'm wondering if it's done because it's more convenient for the code author and/or if it's because there really is no compelling reason to do so.

Edit based on proposed answer:
Questions are:

  1. If I'm stuck with C++03 now but still want to plan for C++11 in the future, is the best option to stick with legacy NULL being set to an integer value and all the best-practices that come with it?
  2. If I'm stuck with something of the #define NULL (0) variety, should I always apply a cast? For example: if(b == static_cast<Bar*>(NULL)) is not something I see done very much and I'm wondering if this is out of laziness or if there are good reasons to do or not do this in the case of comparisons (like null pointer checks exemplified above).

Best Answer

Let's further say that, because of limitations with some of the tools I have that don't support any standards newer than C++03, I have this code in a header:

This is a fantastically bad idea.

The expression (0) is (more or less) equivalent to the C++ definition of the NULL. The thing is, nullptr was invented specifically to deal with shortcomings of the NULL.

Therefore, pretending that they are in some way equivalent will only confuse readers. It will make people used to C++11 write code that has different behavior when compiled on C++03 compilers. For example:

void foo(int);
void foo(Bar*);

foo(nullptr);

C++11 tells us that this must call foo(Bar*). But your C++03 macro will instead call foo(int). Since foo(NULL) would cause the same problem, nullptr was invented to stop that.

So having C++03 code that looks like C++11 code but behaves differently is a terrible idea.

nullptr, by design, pretty much never needs to be cast to a specific pointer type. The only exception is if you're calling some kind of function of the form:

template<typename T>
void foo(T* p);

But even then, you can just use foo<ActualType>(nullptr) and get the same effect as foo(static_cast<ActualType*>(nullptr)).

Your not-nullptr needs casting in the same circumstances that NULL does. Indeed, since it is essentially equivalent to NULL, you should just use NULL. And therefore, you have all of the caveats that NULL has.

And FYI: it's pretty much impossible to create a type in C++03 that has identical behavior to C++11's nullptr_t type. You can get close, by using implicit conversions and so forth. But there will always be corner cases where it doesn't work.

So stop promising nullptr behavior that you cannot ensure.