Objects of a class that does not have operator ==() are converted to another type

Alexey Starinsky

Why objects of class A are converted to bool (or to int) in the following code:

class A
{
public:

    operator bool() const { return true; }
    operator int() const { return 1; }
};

int main()
{
    return A() == A();
}

and it is not clear what are they converted to? to bool or to int?

Barry

We need to find what to do with ==. That's going to involve looking for member, non-member, and built-in candidates for ==. In this case, we don't have any member/non-member candidates, so that part is easy.

The built-in candidates are, from [over.built]/13 (emphasis mine, and abridged):

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

bool operator==(L, R);

The promoted arithmetic types are the integral types after promotion and the floating point types. Any integral type smaller than int (including bool) promotes to int. (float promotes to double, but float is still a "promoted arithmetic type"). The important part of this for us really is that the "promoted arithmetic types" include int, but not bool. So effectively, we have built-in candidates like:

bool operator==(int, int);
bool operator==(int, long);
bool operator==(long, int);
bool operator==(long, long);
bool operator==(int, float);
// etc.

There are a lot of candidates in this set. But we can basically divide them into two groups.

The first group consists entirely of:

bool operator==(int, int);

This candidate is viable, we have a clear best conversion sequence since going through operator int() const is better than going through operator bool() const and then promoting.

The second group consists of every other candidate. For every promoted arithmetic type that is not int, we have two equivalent conversion sequences: one through the bool conversion and one through the int conversion. Neither is better than the other. When I first wrote this answer, I thought that this meant these candidates would be rejected - but that is surprisingly not the case, as T.C. points out: an ambiguous conversion sequence is treated equivalently to any other user-defined conversion sequence.

So from the first group, we have one viable candidate which involves a user-defined conversion sequence. And from the second group, we have a lot of candidates with ambiguous conversion sequences - which importantly are considered equivalently good to the operator==(int, int) candidate from the first group.

As a result, A() == A() is ill-formed. There is no best viable candidate. gcc is wrong to accept this.


Note that gcc does reject very similar other presentations of this same idea:

void check(int, int);
void check(float, float);

check(A(), A()); // gcc and clang reject, msvc accepts

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

Why does the conversion operator need a definition of the class converted to?

ostream in class does not have a type

Rule for Cast operator validity when Interface held type is converted to a final class Type according to JLS

Scala: Objects have same class have different type?

Can a abstract class have a method with a return type of another abstract class?

Does the `is` operator in a `when` expression have to see a "hardcoded" type?

Does MiniKanren have the "not" operator?

does int have an operator==

Does dart have operator >>>?

Does MASM have a :: operator?

Is it possible for objects of the same type/class to have different data attributes?

Is it bad practice to have a static class that does not instantiate objects

Why does Kotlin data class objects have backticks?

class operator with result of Extended type does not work in BDS2006?

Does Kotlin have a way to delegate the implementation of an interface to another class?

Why does the pipeline not work on converted json objects?

Java LinkedHashMap converted to Object is serialized as another class?

Does Eclipse have a tool to merge a type hierarchy into a single class?

C++ class needs to have variable number of references to objects of another class

controlling objects in another class

Can an enum class be converted to the underlying type?

Does matlab have a ternary operator?

Does VBA Have a Ternary Operator?

Does PureScript have a pipe operator?

Does Python have the Elvis operator?

Does Java have an exponential operator?

Why operator `?:` does not have priority?

Does Typescript have Operator Overloading?

Does Jython have a ternary operator?