8
votes

I tested the following code with 3 compilers and got 3 different results: error, warning and ok.

  • GCC (5.3): error: invalid user-defined conversion from ‘std::nullptr_t’ to ‘const Thing&’
  • Clang (3.8): warning: implicit conversion of nullptr constant to 'bool'
  • MSVC (14.1): no error, no warning

Which compiler is correct? I know it's a trivial conversion between a pointer type and bool. But what's about std::nullptr_t and bool?

(In the end, Clang and MSVC are both fine with the code. Clang is a little bit more verbose in a positive way.)

struct Thing
{
    Thing(bool) {}
};

void addThing(const Thing&){}

int main()
{
    addThing(nullptr); // warning or error on this line
}
1

1 Answers

8
votes

This is invalid. According to the rule of boolean conversions:

A prvalue of type std::nullptr_t, including nullptr, can be converted to a prvalue of type bool in context of direct-initialization. The resulting value is false.

Quotes from the standard, §7.14/1 Boolean conversions [conv.bool]

For direct-initialization, a prvalue of type std​::​nullptr_­t can be converted to a prvalue of type bool; the resulting value is false.

The conversion is only allowed for direct-initialization, but not copy-intialization, which including the case for passing argument to a function by value. e.g.

bool b1 = nullptr; // invalid
bool b2 {nullptr}; // valid

So GCC is correct. But Clang is not wrong either; the standard only requires the compiler to "issue a diagnostic" when program is ill-formed, so it must tell you something happens, after that it could do anything.

See Does the C++ standard specify that for some cases the compiling should fail with an error?