VP.
VP.

Reputation: 16765

Logical operator execution order

I have though about operator overloading and come with an interesting code:

#include <iostream>

class A {
public:
    operator bool() {
        return true;
    }

    bool operator!() {
        return false;
    }
};

int main() {
    A a;

    if (!a) {
        std::cout << "HELLO";
    } else {
        std::cout << "WORLD";
    }
    std::cout << std::endl;

    return 0;
}

What will be called first and what after? And why? Is this described anywhere in the cppreference?

P.S. For downvoters and others who think I could not execute this code by myself. I could. I did. I have changed it many times to see it's behavior. So what? This is not an explanation. I have asked for a reference which clearly states what rule this code obeys. The information how it works on my machine does not answer the question - what if this is not even portable across different environments (OSes, maybe processors, and so on)?

Upvotes: 3

Views: 163

Answers (2)

How it works is simple. The compiler parses the source and sees if(!a). It then checks if A defines an operator!. Just so happens that it does. So that gets called.

If it had seen if(a) it would have checked that an A is convertible to something which can be used in the condition of an if. Just so happens that it is indeed convertible.

If there had been no operator!, the compiler would have instead checked that an A can be converted to something which may be logically negated. Then the conversion to bool would have been performed.


BTW, the conversion will happen even in surprising places. For instance a + 1 will compile. Not what we want, I think. It's best to allow it only where a bool is contextually expected. You do that by marking the conversion operator explicit:

explicit operator bool() {
    return true;
}

Upvotes: 7

Bathsheba
Bathsheba

Reputation: 234795

!a is no more than syntactic sugar for a.operator!(), which you have defined: that's the compiler's preferred choice.

So the conversion to bool operator is never a candidate.

You could contrive the latter by writing

if (!(bool)a) {

Upvotes: 4

Related Questions