Question: Does implicit bool conversions always fall back to attempting implicit conversion to void*
? (If such a conversion function exists for the type). If so, why?
Consider the following short program:
#include <iostream>
class Foo{
public:
operator void*() const
{
std::cout << "operator void*() const" << std::endl;
return 0;
}
};
int main()
{
Foo f;
if(f)
std::cout << "True" << std::endl;
else
std::cout << "False" << std::endl;
return 0;
}
The output of this program is:
operator void*() const
False
meaning, the conversion function to void*
was called.
If we tag an explicit
qualifier in front of the conversion function then the implicit conversion to void*
would fail.
Edit:
It seems many answers are that "null pointers can be converted to false
". I understand this, my question was regarding the "if I can't directly call operator bool()
then I will try conversion to any pointer".
If the compiler cannot convert a user-defined type to bool
directly, then it tries to do it indirectly, i.e. convert (via an user-defined conversion) to a type that can be converted to bool
without involving another user-defined conversion. The list of such types includes (and seems to be limited to) the following types:
char
, int
, etc)float
, double
, long double
)void*
belongs here, but it could as well be const std::vector<Something>*
)Note however that only one such indirect conversion must exist. If two or more conversions from the above list are possible, then the compiler will face an ambiguity and will report an error.
For a few references in the Standard:
§6.4.0.4 [stmt.select]
The value of a condition that is an expression is the value of the expression, contextually converted to
bool
for statements other thanswitch
§4.0.4 [conv]
Certain language constructs require that an expression be converted to a Boolean value. An expression
e
appearing in such a context is said to be contextually converted tobool
and is well-formed if and only if the declarationbool t(e);
is well-formed, for some invented temporary variablet
.
§8.5.17 [dcl.init]
The semantics of initializers are as follows. The destination type is the type of the object or reference being initialized and the source type is the type of the initializer expression.
§8.5.17.7 [dcl.init]
Otherwise, if the source type is a (possibly cv-qualified) class type, conversion functions are considered. The applicable conversion functions are enumerated (13.3.1.5), and the best one is chosen through overload resolution (13.3). The user-defined conversion so selected is called to convert the initializer expression into the object being initialized. If the conversion cannot be done or is ambiguous, the initialization is ill-formed.
§13.3.1.5 [over.match.conv]
Assuming that “cv1
T
” is the type of the object being initialized, and “cvS
” is the type of the initializer expression, with S a class type, the candidate functions are selected as follows:The conversion functions of S and its base classes are considered. Those non-explicit conversion functions that are not hidden within
S
and yield typeT
or a type that can be converted to typeT
via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden withinS
and yield typeT
or a type that can be converted to typeT
with a qualification conversion (4.4) are also candidate functions.
§4.13.1 [conv.bool]
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 tofalse
; any other value is converted totrue
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With