Manu343726
Manu343726

Reputation: 14184

Implicit conversion to boolean and comparison with boolean literals

I was answering this question, about the topic of user defined conversions to bool and how to disable other conversions:

struct foo
{
    operator bool() const //Explicit overload for bool
    {
       return true; 
    }

  template<typename T>
  operator T() const = delete; //Everithing which is not a bool (Everithing which  
                               //does not fit in the explicit overload) would  
                               //resolve to this operator and will fail.
};


int main()
{
    foo f;

    bool b = f; //OK
    int i = f;  //ERROR
    char c = f; //ERROR
    etc...
}

Later the OP asked me why conditionals like if( f == true ) failed (Where f is a foo. I have tried that by myself and that surprises me because that comparison with boolean literals leads to a conversion to int (Which is disabled) instead of bool:

int main()
{
    foo f;

    if( f ); //OK, converts to bool
    if( f == true ); //ERROR: Conversion to int, which has been disabled
}  

prog.cpp:20:12: error: use of deleted function ‘foo::operator T() const [with T = int]’ if( f == true);
..............................................................................................................................................^

My question is: Are boolean literals defined as integers (Like the common C macros #define true 1 #define false 0), and if not, why that comparison lead to an int conversion instead of a bool?

I'm using GCC4.8.1 with C++11 enabled ( -std=C++11 ).

Here is an example of that behavior at ideone.

Upvotes: 4

Views: 1364

Answers (3)

dyp
dyp

Reputation: 39151

Since foo is a class type, special rules apply when using an operator that is not specifically defined for that class type, see [over.built]/12

For every pair of promoted arithmetic types L and R, there exist candidate operator functions of the form

LR operator*(L, R);
LR operator/(L, R);
LR operator+(L, R);
LR operator-(L, R);
bool operator<(L, R);
bool operator>(L, R);
bool operator<=(L, R);
bool operator>=(L, R);
bool operator==(L, R);
bool operator!=(L, R);

where LR is the result of the usual arithmetic conversions between types L and R.

Not the usage of the term promoted arithmetic types: This requires a promotion of bool.

A bool is promoted to an int, see [conv.prom]/6 (integral promotions)

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.


So there are candidate functions of the form

common_type<L,int> operator==(L, int);

where L is a promoted arithmetic type. However, there are many of them, for example

common_type<int      , int> operator==(int      , int);
common_type<long     , int> operator==(long     , int);
common_type<long long, int> operator==(long long, int);

Each of which require a user-defined conversion from foo to the promoted type. It is not clear to me why this isn't ambiguous, as foo can be converted to any of them. This is also described in the open issue CWG 954.

If there are several non-template conversion functions, g++4.8.1 and clang++3.5 report this ambiguity. (It should be noted that clang might have a bug here, see this example which works fine with g++4.8.1.)


However, there is no candidate of the form

common_type<bool, int> operator==(bool, int);

as bool is not a promoted arithmetic type. Therefore, the conversion from foo to bool will not be chosen for the expression

foo x;
x == true

Upvotes: 2

Sebastian Hoffmann
Sebastian Hoffmann

Reputation: 11502

Lets do a quick test here:

template <typename T>
struct OutputType;

int main()
{
    OutputType<decltype(true)> a;
}

Atleast ideone outputs here that true is of type bool: http://ideone.com/Gm653T

However:

The type bool can be converted to int with the value false becoming ​0​ and true becoming 1.

Source: cppreference

And my guess is that exactly such a promotion happens here

Upvotes: 0

rholmes
rholmes

Reputation: 4184

Type bool is not #defined in C++. I'm thinking that the comparison promotes to int and requires the int conversion.

Upvotes: 0

Related Questions