peter.slizik
peter.slizik

Reputation: 2076

Invoking conversion operators

What's the reason for the following behavior?

class BoolWrapper
{
public:
    BoolWrapper(bool value) : value(value) {}

    operator bool() const { return value; }
    operator int() const { return (int) value; }

private:
    bool value;
};


BoolWrapper bw(true);

if (bw) { ... }            // invokes operator bool()
if (bw == true) { ... }    // invokes operator int() -- why?

Is this behavior expected? (Using GCC 4.7.2.)

Upvotes: 11

Views: 458

Answers (3)

AnT stands with Russia
AnT stands with Russia

Reputation: 320491

Your expectations are based on your belief that the language already knows how to compare two bool values. In reality it doesn't, however surprising it might sound. More precisely, the language "does not know" how to do it directly.

At the conceptual level, C++ does not have a dedicated built-in equality comparison operator for bool vs. bool comparisons. Even when you write true == false in your code, it is really interpreted by the language as (int) true == (int) false. The implicit conversion to int is introduced by the rules of usual arithmetic conversions and int vs. int comparison is used afterwards.

The most immediate built-in operator that can compare two bool values is the one for int vs. int comparison. This is the operator the compiler is trying to use in your case as well. The very same operator will be used for char vs. char and short vs. short comparisons.

In other words, the only way the compiler can use your bool conversion operator in the bw == true expression would be to do

(int)(bool) bw == (int) true

This is certainly less "optimal" than the direct

(int) bw == (int) true

This is the logic that drives the language to select the latter variant.

Upvotes: 6

Gorpik
Gorpik

Reputation: 11028

In the first case, an if clause expects a bool condition, so this is the selected conversion.

In the second case, you are asking for a comparison between a BoolWrapper and a bool. Since no operator == overload exists to do it, the compiler must convert these arguments into suitable ones. According to the standard (section 4.5, Integral promotions), the preferred integral type for conversions is int. Since both BoolWrapper and bool can be converted to int, this is the selected conversion.

Upvotes: 4

Mark B
Mark B

Reputation: 96241

From 5/9:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

[Some floating point items that don't matter.]

Otherwise, the integral promotions (4.5) shall be performed on both operands.

And from 3.9.1/6 we see that bool is eligible for integral promotion:

Values of type bool are either true or false.42) [Note: there are no signed, unsigned, short, or long bool types or values. ] As described below, bool values behave as integral types. Values of type bool participate in integral promotions (4.5).

Upvotes: 6

Related Questions