I have built the following minimal example:
class A
{
public:
A(const char *s);
private:
const char *p;
};
A::A(const char *s)
:
The OP 's program fails in compilation in g++ & clang++ when use -std=c++11
, -std=c++14
.
See live demo here on g++ 6.1.0. It gives following error
prog.cc: In function 'A foo()':
prog.cc:17:12: error: could not convert 'false' from 'bool' to 'A'
return false;
^~~~~
See live demo here on clang++. It gives following diagnosis.
main.cpp:17:12: error: no viable conversion from returned value of type 'bool' to function return type 'A'
return false;
^~~~~
main.cpp:1:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'bool' to 'const A &' for 1st argument
class A
^
main.cpp:1:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'bool' to 'A &&' for 1st argument
class A
^
main.cpp:10:4: note: candidate constructor not viable: no known conversion from 'bool' to 'const char *' for 1st argument
A::A(const char *s)
^
main.cpp:22:12: error: no viable conversion from returned value of type 'bool' to function return type 'A'
return true;
^~~~
main.cpp:1:7: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'bool' to 'const A &' for 1st argument
class A
^
main.cpp:1:7: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'bool' to 'A &&' for 1st argument
class A
^
main.cpp:10:4: note: candidate constructor not viable: no known conversion from 'bool' to 'const char *' for 1st argument
A::A(const char *s)
^
main.cpp:7:21: warning: private field 'p' is not used [-Wunused-private-field]
const char *p;
^
false should not convert to pointer type since C++11. See similar question here which I've asked sometimes ago.
As published, C++ 11 has the rule "an integral constant expression prvalue of integer type which evaluates to 0
can be converted to any pointer type, yielding the null pointer value of that type." (C++98/03 had a similarly worded rule with the same net effect).
bool
is an integer type, and false
evaluates to 0
. So false
is a valid null pointer constant.
Apart from this extra rule, C++ has no implicit conversions from integral types to pointers. Which is why true
cannot implicitly be converted to a pointer.
However, C++14 changed the definition of a null pointer constant so that only integer literals (and not integral constant expressions) qualify. false
is a boolean literal, not an integer one, so under C++14, the code will not compile.
Furthermore, since the issue was recognised by the standard committee as a defect in C++11, newer C++11 compilers are likely to obey the C++14 rules in this regard and not treat false
as a null pointer constant. Thanks to @Destructor for tracking down the issue status.
As to why two implicit conversions seem to be allowed here: the rule is not "at most one implicit conversion is allowed." The rule is "at most one user-defined conversion is allowed." Pointer conversions (such as converting a null pointer constant to a null pointer value) are not classified as user-defined conversions. So the conversion sequence in your case is a pointer conversion (bool
to const char *
) followed by a user-defined conversion (const char *
to A
).
For 1), false
is of type bool
, and it can be promoted to an int
implicitely:
- the type
bool
can be converted toint
with the valuefalse
becoming 0
andtrue
becoming1
.
So, false
is basically promoted to NULL
/0
(or nullptr
), which can be assigned to a pointer.
For 2), §4.10 states that:
A null pointer constant is an integer literal (2.14.2) with value zero or a prvalue of type std::nullptr_t.
A null pointer constant can be converted to a pointer type; [...]
Only a Null pointer constant
can be converted to a pointer, and a null pointer constant is either an intergral with value 0
or std::nullptr_t
. true
(or 1
for that matter) aren't specified, and thus they can't be converted to a pointer.