# Comparison operators

From cppreference.com
< cpp‎ | language

Compares the arguments.

Operator name | Syntax | Over​load​able | Prototype examples (for class T)
--- | --- | --- | ---
Inside class definition | Outside class definition
equal to | `a == b` | Yes | bool T::operator==(const T2& b) const; | bool operator==(const T& a, const T2& b);
not equal to | `a != b` | Yes | bool T::operator!=(const T2& b) const; | bool operator!=(const T& a, const T2& b);
less than | `a < b` | Yes | bool T::operator<(const T2& b) const; | bool operator<(const T& a, const T2& b);
greater than | `a > b` | Yes | bool T::operator>(const T2& b) const; | bool operator>(const T& a, const T2& b);
less than or equal to | `a <= b` | Yes | bool T::operator<=(const T2& b) const; | bool operator<=(const T& a, const T2& b);
greater than or equal to | `a >= b` | Yes | bool T::operator>=(const T2& b) const; | bool operator>=(const T& a, const T2& b);
three-way comparison (C++20) | `a <=> b` | Yes | `R` T::operator<=>(const T2& b) const;[1] | `R` operator<=>(const T& a, const T2& b);[1]
Notes Where built-in operators return bool, most user-defined overloads also return bool so that the user-defined operators can be used in the same manner as the built-ins. However, in a user-defined operator overload, any type can be used as return type (including void). `T2` can be any type including `T`. ↑ 1.0 1.1 `R` is the return type of `operator<=>` (see below)

### Two-way comparison

The two-way comparison operator expressions have the form

lhs `<` rhs | (1) |
lhs `>` rhs | (2) |
lhs `<=` rhs | (3) |
lhs `>=` rhs | (4) |
lhs `==` rhs | (5) |
lhs `!=` rhs | (6) |

1) Returns true if lhs is less than rhs, false otherwise.
2) Returns true if lhs is greater than rhs, false otherwise.
3) Returns true if lhs is less than or equal to rhs, false otherwise.
4) Returns true if lhs is greater than or equal to rhs, false otherwise.
5) Returns true if lhs is equal to rhs, false otherwise.
6) Returns true if lhs is not equal to rhs, false otherwise.

In all cases, for the built-in operators, lhs and rhs must have either

- arithmetic or enumeration type (see arithmetic comparison operators below)
- pointer type (see pointer comparison operators below)

after the application of the lvalue-to-rvalue, array-to-pointer and function-to-pointer standard conversions. The comparison is deprecated if both operands have array type prior to the application of these conversions. (since C++20)

In any case, the result is a bool prvalue.

#### Arithmetic comparison operators

If the operands have arithmetic or enumeration type (scoped or unscoped), usual arithmetic conversions are performed on both operands following the rules for arithmetic operators. The values are compared after conversions:

##### Example

Run this code

    #include <iostream>

    int main()
    {
        static_assert(sizeof(unsigned char) < sizeof(int),
                      "Can't compare signed and smaller unsigned properly");
        int a = -1;
        int b = 1;
        unsigned int c = 1;
        unsigned char d = 1;

        std::cout
            << std::boolalpha
            << "Comparing two signed values:\n"
            << " -1 == 1 ? " << (a == b) << '\n'
            << " -1 <  1 ? " << (a <  b) << '\n'
            << " -1 >  1 ? " << (a >  b) << '\n'
            << "Comparing signed and unsigned:\n"
            << " -1 == 1 ? " << (a == c) << '\n' // may issue different-signedness warning
            << " -1 <  1 ? " << (a <  c) << '\n' // may issue different-signedness warning
            << " -1 >  1 ? " << (a >  c) << '\n' // may issue different-signedness warning
            << "Comparing signed and smaller unsigned:\n"
            << " -1 == 1 ? " << (a == d) << '\n'
            << " -1 <  1 ? " << (a <  d) << '\n'
            << " -1 >  1 ? " << (a >  d) << '\n';
    }

Output:

    Comparing two signed values:
     -1 == 1 ? false
     -1 <  1 ? true
     -1 >  1 ? false
    Comparing signed and unsigned:
     -1 == 1 ? false
     -1 <  1 ? false
     -1 >  1 ? true
    Comparing signed and smaller unsigned:
     -1 == 1 ? false
     -1 <  1 ? true
     -1 >  1 ? false

#### Pointer comparison operators

Comparison operators can be used to compare two pointers.

Only equality operators (operator== and operator!=) can be used to compare the following pointer pairs:

- two pointers-to-members
- a null pointer constant with a pointer or a pointer-to-member

a std::nullptr_t value with a null pointer constant (which can also be a std::nullptr_t value) | (since C++11)

First, pointer conversions (pointer to member conversions if the arguments are pointers to members), function pointer conversions, (since C++17) and qualification conversions are applied to both operands to obtain the composite pointer type, as follows:

1) If both operands are null pointer constants, the composite pointer type is std::nullptr_t. | (since C++11)

2) If one operand is a null pointer constant, and the other is a pointer, the composite type is exactly the pointer type.
3) If the operands are

- a pointer to cv1 void, and
- a pointer to cv2 `T`, where `T` is an object type or void,

the composite type is "pointer to cv12 void", where cv12 is the union of cv1 and cv2.
4) If the types of the operands are

- `P1`, a pointer to (possibly cv-qualified) `T1`, and
- `P2`, a pointer to (possibly cv-qualified) `T2`,

and if `T1` is the same as `T2` or is a base class of `T2`, then the composite pointer type is the cv-combined type of `P1` and `P2`. Otherwise, if `T2` is a base class of `T1`, then the composite pointer type is the cv-combined type of `P2` and `P1`.
5) If the types of the operands are

- `MP1`, pointer to member of `T1` of type (possibly cv-qualified) `U1`, and
- `MP2`, pointer to member of `T2` of type (possibly cv-qualified) `U2`,

and if `T1` is the same as or derived from `T2`, then the composite pointer type is the cv-combined type of `MP1` and `MP2`. Otherwise, if `T2` is derived from `T1`, then the composite pointer type is the cv-combined type of `MP2` and `MP1`.
6) If the types of the operands `P1` and `P2` are multi-level mixed pointer and pointer to member types with the same number of levels that only differ by cv-qualifications at any of the levels, the composite pointer type is the cv-combined type of `P1` and `P2`.

In the definition above, cv-combined type of two pointer types `P1` and `P2` is a type `P3` that has the same number of levels and type at every level as `P1`, except that cv-qualifications at every level are set as follows:

a) at every level other than top level, the union of the cv-qualifications of `P1` and `P2` at that level,
b) if the resulting cv-qualification at any level is different from `P1`'s or `P2`'s cv-qualification at the same level, then const is added to every level between the top level and this one.

For example, the composite pointer type of void* and const int* is const void*. The composite pointer type of int** and const int** is const int* const*. Note that until the resolution of CWG issue 1512 (N3624), int** and const int** could not be compared.

In addition to the above, the composite pointer type between pointer to function and pointer to noexcept function (as long as the function type is the same) is pointer to function. | (since C++17)

Note that this implies that any pointer can be compared with void*.

The result of comparing two pointers to objects (after conversions) is defined as follows:

1) If two pointers point to different elements of the same array, or to subobjects within different elements of the same array, the pointer to the element with the higher subscript compares greater. In other words, the results of comparing the pointers is the same as the result of comparing the indexes of the elements they point to.
2) If one pointer points to an element of an array, or to a subobject of the element of the array, and another pointer points one past the last element of the array, the latter pointer compares greater. Pointers to non-array objects are treated as pointers to arrays of one: &obj + 1 compares greater than &obj.
3) If, within an object of non-union class type, two pointers point to different non-zero-sized (since C++20) non-static data members with the same member access (until C++23), or to subobjects or array elements of such members, recursively, the pointer to the later declared member compares greater. In other words, class members in each of the three member access modes (until C++23) are positioned in memory in order of declaration.

The result of equality comparison of two pointers (after conversions) is defined as follows:

1) If the pointers are both null pointer values, they compare equal.
2) If the pointers are pointers to function and point to the same function, they compare equal.
3) If the pointers are pointers to object and represent the same address, they compare equal (this includes two pointers to non-static members of the same union, pointers to standard-layout struct and to its first member, pointers related by `reinterpret_cast`, etc).
4) All other pointers compare unequal.

The result of comparing two pointers to members (after conversions) is defined as follows:

1) If both pointers to member are null member pointer values, they compare equal.
2) Otherwise, if only one of two pointers to member is the null member pointer value, they compare unequal.
3) Otherwise, if either is a pointer to a virtual member function, the result is unspecified.
4) Otherwise, if one refers to a member of class `C1` and the other refers to a member of a different class `C2`, where neither is a base class of the other, the result is unspecified.

    struct A {};
    struct B : A { int x; };
    struct C : A { int x; };

    int A::*bx = (int(A::*)) &B::x;
    int A::*cx = (int(A::*)) &C::x;

    bool b1 = (bx == cx); // unspecified

5) Otherwise, if both refer to (possibly different) members of the same union, they compare equal.
6) Otherwise, two pointers to member compare equal if and only if they would refer to the same member of the same most derived object or the same subobject if they were dereferenced with a hypothetical object of the associated class type.
7) Otherwise they compare unequal.

    struct B
    {
        int f();
    };
    struct L : B {};
    struct R : B {};
    struct D : L, R {};

    int (B::*pb)() = &B::f;
    int (L::*pl)() = pb;
    int (R::*pr)() = pb;
    int (D::*pdl)() = pl;
    int (D::*pdr)() = pr;

    bool x = (pdl == pdr); // false
    bool y = (pb == pl);   // true

If a pointer p compare equal to pointer q, p <= q and p >= q both yield true and p < q and p > q both yield false.

If a pointer p compares greater than a pointer q, then p >= q, p > q, q <= p, and q < p all yield true and p <= q, p < q, q >= p, and q > p all yield false.

If two pointers are not specified to compare greater or compare equal, the result of the comparison is unspecified. An unspecified result may be nondeterministic, and need not be consistent even for multiple evaluations of the same expression with the same operands in the same execution of the program:

    int x, y;

    bool f(int* p, int* q) { return p < q; }

    assert(f(&x, &y) == f(&x, &y)); // may fire in a conforming implementation

In overload resolution against user-defined operators, for every pair of promoted arithmetic types `L` and `R`, including enumeration types, the following function signatures participate in overload resolution:

bool operator<(L, R); |  |
bool operator>(L, R); |  |
bool operator<=(L, R); |  |
bool operator>=(L, R); |  |
bool operator==(L, R); |  |
bool operator!=(L, R); |  |

For every type `P` which is either pointer to object or pointer to function, the following function signatures participate in overload resolution:

bool operator<(P, P); |  |
bool operator>(P, P); |  |
bool operator<=(P, P); |  |
bool operator>=(P, P); |  |
bool operator==(P, P); |  |
bool operator!=(P, P); |  |

For every type `MP` that is a pointer to member object or pointer to member function or std::nullptr_t, the following function signatures participate in overload resolution:

bool operator==(MP, MP); |  |
bool operator!=(MP, MP); |  |

##### Example

Run this code

    #include <iostream>

    struct Foo
    {
        int n1;
        int n2;
    };

    union Union
    {
        int n;
        double d;
    };

    int main()
    {
        std::cout << std::boolalpha;

        char a[4] = "abc";
        char* p1 = &a[1];
        char* p2 = &a[2];
        std::cout << "Pointers to array elements:\n"
                  << "p1 == p2? " << (p1 == p2) << '\n'
                  << "p1 <  p2? " << (p1 <  p2) << '\n';

        Foo f;
        int* p3 = &f.n1;
        int* p4 = &f.n2;
        std::cout << "Pointers to members of a class:\n"
                  << "p3 == p4? " << (p3 == p4) << '\n'
                  << "p3 <  p4? " << (p3 <  p4) << '\n';

        Union u;
        int* p5 = &u.n;
        double* p6 = &u.d;
        std::cout << "Pointers to members of a union:\n"
                  << "p5 == (void*)p6? " << (p5 == (void*)p6) << '\n'
                  << "p5 <  (void*)p6? " << (p5 <  (void*)p6) << '\n';
    }

Output:

    Pointers to array elements:
    p1 == p2? false
    p1 <  p2? true
    Pointers to members of a class:
    p3 == p4? false
    p3 <  p4? true
    Pointers to members of a union:
    p5 == (void*)p6? true
    p5 <  (void*)p6? false

#### Notes

Because these operators group left-to-right, the expression a < b < c is parsed (a < b) < c, and not a < (b < c) or (a < b) && (b < c).

Run this code

    #include <iostream>

    int main()
    {
        int a = 3, b = 2, c = 1;

        std::cout << std::boolalpha
            << (a < b < c) << '\n' // true; maybe warning
            << ((a < b) < c) << '\n' // true
            << (a < (b < c)) << '\n' // false
            << ((a < b) && (b < c)) << '\n'; // false
    }

A common requirement for user-defined operator< is strict weak ordering. In particular, this is required by the standard algorithms and containers that work with Compare types: std::sort, std::max_element, std::map, etc.

Although the results of comparing pointers of random origin (e.g. not all pointing to members of the same array) is unspecified, many implementations provide strict total ordering of pointers, e.g. if they are implemented as addresses within continuous virtual address space. Those implementations that do not (e.g. where not all bits of the pointer are part of a memory address and have to be ignored for comparison, or an additional calculation is required or otherwise pointer and integer is not a 1 to 1 relationship), provide a specialization of std::less for pointers that has that guarantee. This makes it possible to use all pointers of random origin as keys in standard associative containers such as std::set or std::map.

For the types that are both EqualityComparable and LessThanComparable, the C++ standard library makes a distinction between equality, which is the value of the expression a == b and equivalence, which is the value of the expression !(a < b) && !(b < a).

Comparison between pointers and null pointer constants was removed by the resolution of CWG issue 583 included in N3624:

Run this code

    void f(char* p)
    {
        if (p > 0) { /*...*/ } // Error with N3624, compiled before N3624
        if (p > nullptr) { /*...*/ } // Error with N3624, compiled before N3624
    }

    int main() {}

### Three-way comparison The three-way comparison operator expressions have the form
a `<=>` b |  |
The expression returns an object such that (a <=> b) < 0 if a < b, (a <=> b) > 0 if a > b, (a <=> b) == 0 if a and b are equal/equivalent. If one of the operands is of type bool and the other is not, the program is ill-formed. If both operands have arithmetic types, or if one operand has unscoped enumeration type and the other has integral type, the usual arithmetic conversions are applied to the operands, and then If a narrowing conversion is required, other than from an integral type to a floating point type, the program is ill-formed. Otherwise, if the operands have integral type, the operator yields a prvalue of type `std::strong_ordering`: std::strong_ordering::equal if both operands are arithmetically equal, std::strong_ordering::less if the first operand is arithmetically less than the second, std::strong_ordering::greater otherwise. Otherwise, the operands have floating-point type, and the operator yields a prvalue of type `std::partial_ordering`. The expression a <=> b yields std::partial_ordering::less if a is less than b, std::partial_ordering::greater if a is greater than b, std::partial_ordering::equivalent if a is equivalent to b (-0 <=> +0 is equivalent), std::partial_ordering::unordered (NaN <=> anything is unordered). If both operands have the same enumeration type `E`, the operator yields the result of converting the operands to the underlying type of E and applying <=> to the converted operands. If at least one of the operands is a pointer or pointer-to-member, array-to-pointer conversions, derived-to-base pointer conversions, function pointer conversions, and qualification conversions are applied as necessary to convert both operands to the same pointer type, and the resulting pointer type is an object pointer type, p <=> q returns a prvalue of type `std::strong_ordering`: std::strong_ordering::equal if p == q, std::strong_ordering::less if p < q, std::strong_ordering::greater if p > q, unspecified result if comparison is unspecified for these pointer values (such as when they do not point into the same object or array). Otherwise, the program is ill-formed. In overload resolution against user-defined operators, for pointer or enumeration type `T`, the following function signature participates in overload resolution:
R operator<=>(T, T); |  |
Where `R` is the ordering category type defined above. #### Example Run this code
    #include <compare>
    #include <iostream>

    int main()
    {
        double foo = -0.0;
        double bar = 0.0;

        auto res = foo <=> bar;

        if (res < 0)
            std::cout << "-0 is less than 0";
        else if (res > 0)
            std::cout << "-0 is greater than 0";
        else if (res == 0)
            std::cout << "-0 and 0 are equal";
        else
            std::cout << "-0 and 0 are unordered";
    }
Output:
    -0 and 0 are equal
#### Notes Three-way comparison can be automatically generated for class types, see default comparisons. If both of the operands are arrays, three-way comparison is ill-formed.
    unsigned int i = 1;
    auto r = -1 < i;    // existing pitfall: returns ‘false’
    auto r2 = -1 <=> i; // Error: narrowing conversion required
| (since C++20)

Feature-test macro | Value | Std | Comment
--- | --- | --- | ---
`__cpp_impl_three_way_comparison` | 201907L | (C++20) | Three-way comparison (compiler support)
`__cpp_lib_three_way_comparison` | 201907L | (C++20) | Three-way comparison (library support); adding three-way comparison to the library

### Standard library

Comparison operators are overloaded for many classes in the standard library.

operator==operator!= (removed in C++20) | checks whether the objects refer to the same type (public member function of `std::type_info`)
operator==operator!=operator<operator<=> (removed in C++20)(removed in C++20)(C++20) | compares two `error_code`s (function)
operator==operator!=operator<operator<=> (removed in C++20)(removed in C++20)(C++20) | compares `error_condition`s and `error_code`s (function)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the pair (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the tuple (function template)
operator==operator!= (removed in C++20) | compares the contents (public member function of `std::bitset<N>`)
operator==operator!= (removed in C++20) | compares two allocator instances (public member function of `std::allocator<T>`)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(C++20) | compares to another `unique_ptr` or with nullptr (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | compares with another `shared_ptr` or with nullptr (function template)
operator==operator!= (removed in C++20) | compares a std::function with nullptr (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20) | compares two durations (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20) | compares two time points (function template)
operator==operator!= (removed in C++20) | compares two scoped_allocator_adaptor instances (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(C++20) | compares the underlying std::type_info objects (public member function of `std::type_index`)
operator==operator!=operator<operator>operator<=operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares two strings (function template)
operator==operator!= (removed in C++20) | equality comparison between locale objects (public member function of `std::locale`)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the array (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the deque (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the forward_list (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the list (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the vector (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the map (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the multimap (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the set (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | lexicographically compares the values in the multiset (function template)
operator==operator!= (removed in C++20) | compares the values in the unordered_map (function template)
operator==operator!= (removed in C++20) | compares the values in the unordered_multimap (function template)
operator==operator!= (removed in C++20) | compares the values in the unordered_set (function template)
operator==operator!= (removed in C++20) | compares the values in the unordered_multiset (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++20) | lexicographically compares the values in the queue (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++20) | lexicographically compares the values in the stack (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++20) | compares the underlying iterators (function template)
operator==operator!=operator<operator<=operator>operator>=operator<=> (C++11)(C++11)(removed in C++20)(C++11)(C++11)(C++11)(C++11)(C++20) | compares the underlying iterators (function template)
operator==operator!= (removed in C++20) | compares two `istream_iterator`s (function template)
operator==operator!= (removed in C++20) | compares two `istreambuf_iterator`s (function template)
operator==operator!= (removed in C++20) | compares two complex numbers or a complex and a scalar (function template)
operator==operator!=operator<operator<=operator>operator>= | compares two valarrays or a valarray with a value (function template)
operator==operator!= (C++11)(C++11)(removed in C++20) | compares the internal states of two pseudo-random number engines (function)
operator==operator!= (C++11)(C++11)(removed in C++20) | compares two distribution objects (function)
operator==operator!=operator<operator<=operator>operator>=operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | compares a `sub_match` with another `sub_match`, a string, or a character (function template)
operator==operator!= (removed in C++20) | lexicographically compares the values in the two match result (function template)
operator==operator!= (removed in C++20) | compares two `regex_iterator`s (public member function of `std::regex_iterator<BidirIt,CharT,Traits>`)
operator==operator!= (removed in C++20) | compares two `regex_token_iterator`s (public member function of `std::regex_token_iterator<BidirIt,CharT,Traits>`)
operator==operator!=operator< operator<= operator> operator>= operator<=> (removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20) | compares two `thread::id` objects (function)

The namespace `std::rel_ops` provides generic operators !=, >, <=, and >=:

Defined in header `<utility>`
Defined in namespace `std::rel_ops`
operator!=operator>operator<=operator>= (deprecated in C++20) | automatically generates comparison operators based on user-defined operator== and operator< (function template)

### Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR | Applied to | Behavior as published | Correct behavior
--- | --- | --- | ---
CWG 583 (N3624) | C++98 | all six comparison operators could be used to compare a pointer with a null pointer constant | only equality operators allowed
CWG 661 | C++98 | the actual semantics of arithmetic comparisons (e.g. whether 1 < 2 yields true or false) were unspecified | specification added
CWG 879 | C++98 | pointers to function types and pointers to void did not have built-in comparisons | added comparison specification for these pointers
CWG 1512 (N3624) | C++98 | the rule of composite pointer type was incomplete, and thus did not allow comparison between int** and const int** | made complete
CWG 1596 | C++98 | non-array objects were considered to belong to arrays with one element only for the purpose of pointer arithmetic | the rule is also applied to comparison
CWG 1598 | C++98 | two pointers to members of classes that are different and neither is the base class of the other did not compare equal even if the offsets of the pointed members can be the same | the result is unspecified in this case
CWG 1858 | C++98 | it was not clear whether two pointers to members that refer to different members of the same union compare equal as if they refer to the same member | they compare equal in this case
CWG 2419 | C++98 | a pointer to non-array object was only treated as a pointer to the first element of an array with size 1 in pointer comparison if the pointer is obtained by `&` | applies to all pointers to non-array objects
CWG 2526 | C++98 | the definition of relational comparison (`>`, `>=`, `<` and `<=`) of pointers to void and function pointers were removed by N3624 | restored

### See also

- Operator precedence

- Operator overloading

- Compare (named requirements)

Common operators
assignment | increment decrement | arithmetic | logical | comparison | member access | other
a = b a += b a -= b a *= b a /= b a %= b a &= b a |= b a ^= b a <<= b a >>= b | ++a --a a++ a-- | +a -a a + b a - b a * b a / b a % b ~a a & b a | b a ^ b a << b a >> b | !a a && b a || b | a == b a != b a < b a > b a <= b a >= b a <=> b | a[...] *a &a a->b a.b a->*b a.*b | function call
a(...)
comma
a, b
conditional
a ? b : c
Special operators
`static_cast` converts one type to another related type `dynamic_cast` converts within inheritance hierarchies `const_cast` adds or removes cv-qualifiers `reinterpret_cast` converts type to unrelated type C-style cast converts one type to another by a mix of `static_cast`, `const_cast`, and `reinterpret_cast` `new` creates objects with dynamic storage duration `delete` destructs objects previously created by the new expression and releases obtained memory area `sizeof` queries the size of a type `sizeof...` queries the size of a parameter pack (since C++11) `typeid` queries the type information of a type `noexcept` checks if an expression can throw an exception (since C++11) `alignof` queries alignment requirements of a type (since C++11)

Retrieved from "https://en.cppreference.com/mwiki/index.php?title=cpp/language/operator_comparison&oldid=156315"