11 Classes [class]

11.11 Comparisons [class.compare]

11.11.1 Defaulted comparison operator functions [class.compare.default]

A defaulted comparison operator function ([over.binary]) for some class C shall be a non-template function declared in the member-specification of C that is
  • a non-static const member of C having one parameter of type const C&, or
  • a friend of C having either two parameters of type const C& or two parameters of type C.
A defaulted comparison operator function for class C is defined as deleted if any non-static data member of C is of reference type or C is a union-like class ([class.union.anon]).
If the class definition does not explicitly declare an == operator function, but declares a defaulted three-way comparison operator function, an == operator function is declared implicitly with the same access as the three-way comparison operator function.
The implicitly-declared == operator for a class X is an inline member and is defined as defaulted in the definition of X.
If the three-way comparison operator function is declared as a non-static const member, the implicitly-declared == operator function is a member of the form
bool X::operator==(const X&) const;
Otherwise, the implicitly-declared == operator function is of the form
friend bool operator==(const X&, const X&);
Note
: Such a friend function is visible to argument-dependent lookup ([basic.lookup.argdep]) only ([namespace.memdef]). — end note
 ]
The operator is a constexpr function if its definition would satisfy the requirements for a constexpr function.
Note
:
The == operator function is declared implicitly even if the defaulted three-way comparison operator function is defined as deleted.
— end note
 ]
The direct base class subobjects of C, in the order of their declaration in the base-specifier-list of C, followed by the non-static data members of C, in the order of their declaration in the member-specification of C, form a list of subobjects.
In that list, any subobject of array type is recursively expanded to the sequence of its elements, in the order of increasing subscript.
Let be an lvalue denoting the element in the expanded list of subobjects for an object x (of length n), where is formed by a sequence of derived-to-base conversions ([over.best.ics]), class member access expressions ([expr.ref]), and array subscript expressions ([expr.sub]) applied to x.
It is unspecified whether virtual base class subobjects appear more than once in the expanded list of subobjects.

11.11.2 Equality operators [class.eq]

A defaulted equality operator function ([over.binary]) shall have a declared return type bool.
A defaulted == operator function for a class C is defined as deleted unless, for each in the expanded list of subobjects for an object x of type C, is a valid expression and contextually convertible to bool.
The return value V of a defaulted == operator function with parameters x and y is determined by comparing corresponding elements and in the expanded lists of subobjects for x and y (in increasing index order) until the first index i where yields a result value which, when contextually converted to bool, yields false.
If no such index exists, V is true.
Otherwise, V is false.
A defaulted != operator function for a class C with parameters x and y is defined as deleted if
  • overload resolution ([over.match]), as applied to x == y, does not result in a usable function, or
  • x == y is not a prvalue of type bool.
Otherwise, the operator function yields !(x == y).
Example
:
struct D {
  int i;
  friend bool operator==(const D& x, const D& y) = default;
                                                // OK, returns x.i == y.i
  bool operator!=(const D& z) const = default;  // OK, returns !(*this == z)
};
— end example
 ]

11.11.3 Three-way comparison [class.spaceship]

The synthesized three-way comparison of type R ([cmp.categories]) of glvalues a and b of the same type is defined as follows:
  • If overload resolution for a <=> b results in a usable function ([over.match]), static_­cast<R>(a <=> b).
  • Otherwise, if overload resolution for a <=> b finds at least one viable candidate, the synthesized three-way comparison is not defined.
  • Otherwise, if R is strong_­ordering, then
    a == b ? strong_ordering::equal :
    a < b  ? strong_ordering::less :
             strong_ordering::greater
    
  • Otherwise, if R is weak_­ordering, then
    a == b ? weak_ordering::equivalent :
    a < b  ? weak_ordering::less :
             weak_ordering::greater
    
  • Otherwise, if R is partial_­ordering, then
    a == b ? partial_ordering::equivalent :
    a < b  ? partial_ordering::less :
    b < a  ? partial_ordering::greater :
             partial_ordering::unordered
    
  • Otherwise, the synthesized three-way comparison is not defined.
Note
:
A synthesized three-way comparison may be ill-formed if overload resolution finds usable functions that do not otherwise meet the requirements implied by the defined expression.
— end note
 ]
Let R be the declared return type of a defaulted three-way comparison operator function.
Given an expanded list of subobjects for an object x of type C, let be the type of the expression <=> , or void if overload resolution applied to that expression does not find a usable function.
  • If R is auto, then the return type is deduced as the common comparison type (see below) of , , , .
    If the return type is deduced as void, the operator function is defined as deleted.
  • Otherwise, if the synthesized three-way comparison of type R between any objects and is not defined or would be ill-formed, the operator function is defined as deleted.
The return value V of type R of the defaulted three-way comparison operator function with parameters x and y of the same type is determined by comparing corresponding elements and in the expanded lists of subobjects for x and y (in increasing index order) until the first index i where the synthesized three-way comparison of type R between and yields a result value where , contextually converted to bool, yields true; V is .
If no such index exists, V is static_­cast<R>(std​::​strong_­ordering​::​equal).
The common comparison type U of a possibly-empty list of n types , , , is defined as follows:
  • If any is not a comparison category type ([cmp.categories]), U is void.
  • Otherwise, if at least one is std​::​partial_­ordering, U is std​::​partial_­ordering ([cmp.partialord]).
  • Otherwise, if at least one is std​::​weak_­ordering, U is std​::​weak_­ordering ([cmp.weakord]).
  • Otherwise, U is std​::​strong_­ordering ([cmp.strongord]).
    Note
    :
    In particular, this is the result when n is 0.
    — end note
     ]

11.11.4 Relational operators [class.rel]

A defaulted relational operator function ([over.binary]) for some operator @ shall have a declared return type bool.
The operator function with parameters x and y is defined as deleted if
  • overload resolution ([over.match]), as applied to x <=> y, does not result in a usable function, or
  • the operator @ cannot be applied to the return type of x <=> y.
Otherwise, the operator function yields x <=> y @ 0.
Example
:
struct HasNoLessThan { };

struct C {
  friend HasNoLessThan operator<=>(const C&, const C&);
  bool operator<(const C&) const = default;             // OK, function is deleted
};
— end example
 ]