Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++, does bool conversion always fall back to implicit conversion to void*?

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".

like image 881
jensa Avatar asked Jul 22 '16 21:07

jensa


2 Answers

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:

  • an integer arithmetic type (char, int, etc)
  • a floating point arithmetic type (float, double, long double)
  • a pointer type (void* belongs here, but it could as well be const std::vector<Something>*)
  • a pointer to function (including a pointer to a member function)
  • a reference type to any of the above

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.

like image 153
Leon Avatar answered Oct 17 '22 22:10

Leon


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 than switch

  • §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 to bool and is well-formed if and only if the declaration bool t(e); is well-formed, for some invented temporary variable t.

  • §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 “cv S 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 type T or a type that can be converted to type T via a standard conversion sequence (13.3.3.1.1) are candidate functions. For direct-initialization, those explicit conversion functions that are not hidden within S and yield type T or a type that can be converted to type T 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 to false; any other value is converted to true.

like image 6
peppe Avatar answered Oct 17 '22 22:10

peppe