P0W
P0W

Reputation: 47814

Why "bool c = nullptr ;" compiles (C++11)?

I don't understand why following code compiles ?

int main()
{
     //int a = nullptr;  // Doesn't Compile
     //char b = nullptr; // Doesn't Compile
       bool c = nullptr; // Compiles

       return 0;
}

whereas the commented section doesn't.


I've already gone through this and this.

Both bool and nullptr are keywords, so what's unique about the other data types?

Upvotes: 29

Views: 6265

Answers (4)

iampranabroy
iampranabroy

Reputation: 1796

C++11 corrects this by introducing a new keyword to serve as a distinguished null pointer constant: nullptr. It is of type nullptr_t, which is implicitly convertible and comparable to any pointer type or pointer-to-member type. It is not implicitly convertible or comparable to integral types, except for bool. While the original proposal specified that an rvalue of type nullptr should not be convertible to bool, the core language working group decided that such a conversion would be desirable, for consistency with regular pointer types. The proposed wording changes were unanimously voted into the Working Paper in June 2008.[2]

For backwards compatibility reasons, 0 remains a valid null pointer constant.

char *pc = nullptr;     // OK
int  *pi = nullptr;     // OK
bool   b = nullptr;     // OK. b is false.
int    i = nullptr;     // error

Upvotes: 0

Cheers and hth. - Alf
Cheers and hth. - Alf

Reputation: 145299

For the same reason as

if( p ) { ... }

compiles: any value of basic type converts implicitly to boolean, with 0 converting to false and any other value to true.

Originally basic type values had to convert to bool for C compatibility. C didn't originally have a bool type, but any numerical expression could be used as a boolean (with the 0 == false convention). And now we're caught in the backward compatibility tangle. nullptr has to support idiomatic constructs such as if(p), especially for the cases where old code's literal 0 or NULL is replaced with nullptr. E.g. code like if(p) can result from a macro expansion, or in template code.


Addendum: the technical how of why nullptr doesn't convert to e.g. int.

Since nullptr converts implicitly to bool, and bool (unfortunately) converts implicitly to int, one could expect that nullptr should also convert to int. But the point of nullptr is that it should behave as a pointer value. And while pointers do convert implicitly to bool, they do not convert implicitly to numerical types.

Arranging such a restriction for a user-defined type is however not entirely straightforward. An operator bool conversion will be invoked for conversion to int, if it's present. One C++11 solution to enfore the restriction, is to make the conversion operator a template, restricted by a std::enable_if, as follows:

#include <type_traits>  // std::enable_if, std::is_same

struct S
{
    template< class Type >
    operator Type* () const { return 0; }

    template<
        class Bool_type,
        class Enabled = typename std::enable_if<
            std::is_same<Bool_type, bool>::value, void
            >::type
        >
    operator Bool_type () const { return false; }
};

auto main() -> int
{
    bool const              b   = S();      // OK.
    double const*  const    p   = S();      // OK.
    int const               i   = S();      // !Doesn't compile.
}

Upvotes: 41

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 507055

In http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654 , Jason Merril argues

Anything we can do with an arbitrary pointer, we ought to be able to do with nullptr_t as well.

I think the following (slightly artificial) example supports that argument (although I am not totally sure if it was intended for this case)

template<typename T, typename P>
void safeProcess(T pointer, P &processor) {
  bool isNonNull(pointer);
  if(isNonNull) {
    processor.process(pointer);
  }
}

Which would allow passing nullptr along with other pointer types compatible with whatever processor.process accepts.

Upvotes: 4

Yu Hao
Yu Hao

Reputation: 122403

C++11 §4.12 Boolean conversions

A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. A prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.

It's true that nullptr is a keyword, but it's a null pointer literal, not the same role as bool. Think about the boolean literals, true and false are also keywords.

Upvotes: 18

Related Questions