My understanding is that, nullptr could not be converted implicitly to another types. But later I "found" that it could be converted to bool. The issue is, I can see it being converted to bool on GCC 4.x, but it complains on GCC > 5.X
#include <iostream>
bool f(bool a){
return !a;
}
// Type your code here, or load an example.
int main() {
return f(nullptr);
}
On >5.x I get
<source>: In function 'int main()':
<source>:7:21: error: converting to 'bool' from 'std::nullptr_t' requires direct-initialization [-fpermissive]
return f(nullptr);
^
<source>:2:6: note: initializing argument 1 of 'bool f(bool)'
bool f(bool a){
^
Compiler returned: 1
I couldn't find anything on the release notes of GCC 5.X that would explain that.
Can be observed here: https://godbolt.org/g/1Uc2nM
Can someone explain why there is a difference between versions and what rule is applied here.
The rule can be found in C++17 [conv.bool]/1:
For direct-initialization, a prvalue of type
std::nullptr_t
can be converted to a prvalue of typebool
; the resulting value is false.
Initialization of function parameters is copy-initialization , not direct-initialization. If you are not familiar with this topic; initialization contexts in C++ can be divided into these two classes, and there are some operations that can only occur in direct-initialization.
The restriction to direct-initialization was added in C++14, which could explain the difference between g++ versions.
I assume the purpose of this rule is to raise an error for the exact code you've written: a bool
is expected and a null pointer constant was provided; testing a null pointer constant for boolean-ness is not very meaningful since it only has one state anyway.
Remember that nullptr
is not a pointer; it's a thing that can be implicitly converted to a null pointer if the code explicitly requests such a conversion. The whole reason for adding it was to fix the hack of 0
being used as a null pointer constant, and inadvertently matching some other template or overload.
The code could be:
return f(static_cast<bool>(nullptr));
or perhaps you could add an overload of f
that accepts std::nullptr_t
.