Equality operator overloads: Is (x!=y) == (!(x==y))?

后端 未结 3 1231
南方客
南方客 2021-01-17 07:49

Does the C++ standard guarantee that (x!=y) always has the same truth value as !(x==y)?


I know there are many subtleties inv

3条回答
  •  不思量自难忘°
    2021-01-17 08:03

    Does the C++ standard guarantee that (x!=y) always has the same truth value as !(x==y)?

    No it doesn't. Absolutely nothing stops me from writing:

    struct Broken {
        bool operator==(const Broken& ) const { return true; }
        bool operator!=(const Broken& ) const { return true; }
    };
    
    Broken x, y;
    

    That is perfectly well-formed code. Semantically, it's broken (as the name might suggest), but there's certainly nothing wrong from it from a pure C++ code functionality perspective.

    The standard also clearly indicates this is okay in [over.oper]/7:

    The identities among certain predefined operators applied to basic types (for example, ++a ≡ a+=1) need not hold for operator functions. Some predefined operators, such as +=, require an operand to be an lvalue when applied to basic types; this is not required by operator functions.

    In the same vein, nothing in the C++ standard guarantees that operator< actually implements a valid Ordering (or that x !(x>=y), etc.). Some standard library implementations will actually add instrumentation to attempt to debug this for you in the ordered containers, but that is just a quality of implementation issue and not a standards-compliant-based decision.


    Library solutions like Boost.Operators exist to at least make this a little easier on the programmer's side:

    struct Fixed : equality_comparable {
        bool operator==(const Fixed&) const;
        // a consistent operator!= is provided for you
    };
    

    In C++14, Fixed is no longer an aggregate with the base class. However, in C++17 it's an aggregate again (by way of P0017).


    With the adoption of P1185 for C++20, the library solution has effectively becomes a language solution - you just have to write this:

    struct Fixed {
        bool operator==(Fixed const&) const;
    };
    
    bool ne(Fixed const& x, Fixed const& y) {
        return x != y;
    }
    

    The body of ne() becomes a valid expression that evaluates as !x.operator==(y) -- so you don't have to worry about keeping the two comparison in line nor rely on a library solution to help out.

提交回复
热议问题