c++operator-overloadingnot-operator

Overloading logical NOT operator vs bool type-cast operator


Consider the following code:

class Truth
{
public:
    Truth(bool val) : value(val) {}
    bool operator!() {std::cout<<"operator!()"<<std::endl; return !value;}
    operator bool() {std::cout<<"operator bool()"<<std::endl; return value;}
private:
    bool value;
};

int main()
{
    Truth t(true);

    if(!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(!!t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    if(t)
        std::cout<<"t is false"<<std::endl;
    else
        std::cout<<"t is true"<<std::endl;

    return 0;
}

In the statements if(!t) and if(!!t) the overloaded operator!() implementation gets called, whereas (not surprinsingly) in the statement if(t) the overloaded operator bool() implementation gets called instead.

However if the operator!() implementation is commented out, in all 3 statements, operator bool() gets called.

I understand the "why" this happens, but my concern is that, overloading logical NOT operator (!) seems to miss half of the truth evaluation semantics while bool type-cast operator appears to cover them nicely.

Am I missing something or should the overloading of logical NOT operator be discouraged in favor of bool type-cast?


Solution

  • In C++11, you can simply overload explicit operator bool(). There's no reason to overload operator! unless you want it to do something different - and if you think you want that, you should probably think again.

    Historically, overloading operator bool would open the door to implicit conversion to any numeric type, which could cause confusion, ambiguities, and subtle bugs; so it was better not to do that. Overloading operator! was a simple way to allow some use in conditionals, without opening that door, if you didn't want to get bogged down with the safe bool idiom. (The link is for historical interest only; the idiom is obsolete in C++11, thanks to explicit conversion operators.)