10 Classes [class]

10.10 Comparisons [class.compare]

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

A defaulted comparison operator function ([expr.spaceship], [expr.rel], [expr.eq]) for some class C shall be a non-template function declared in the member-specification of C that is
  • a non-static member of C having one parameter of type const C&, or
  • a friend of C having two parameters of type const C&.
A three-way comparison operator for a class type C is a structural comparison operator if it is defined as defaulted in the definition of C, and all three-way comparison operators it invokes are structural comparison operators.
A type T has strong structural equality if, for a glvalue x of type const T, x <=> x is a valid expression of type std::strong_­ordering or std::strong_­equality and either does not invoke a three-way comparison operator or invokes a structural comparison operator.

10.10.2 Three-way comparison [class.spaceship]

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.
The type of the expression <=> is denoted by .
It is unspecified whether virtual base class subobjects are compared more than once.
If the declared return type of a defaulted three-way comparison operator function is auto, then the return type is deduced as the common comparison type (see below) of , , , .
Otherwise, the program will be ill-formed if the expression <=> is not implicitly convertible to the declared return type for any i.
end note
If the return type is deduced as void, 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 until the first index i where <=> yields a result value where , contextually converted to bool, yields true; V is converted to R.
If no such index exists, V is std::strong_­ordering::equal converted to R.
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::weak_­equality, or at least one is std::strong_­equality and at least one is std::partial_­ordering or std::weak_­ordering, U is std::weak_­equality ([cmp.weakeq]).
  • Otherwise, if at least one is std::strong_­equality, U is std::strong_­equality ([cmp.strongeq]).
  • 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]).
    In particular, this is the result when n is 0.
    end note

10.10.3 Other comparison operators [class.rel.eq]

A defaulted relational ([expr.rel]) or equality ([expr.eq]) operator function 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 (also considering synthesized candidates with reversed order of parameters ([over.match.oper])), results in an ambiguity or a function that is deleted or inaccessible from the operator function, or
  • the operator @ cannot be applied to the return type of x <=> y or y <=> x.
Otherwise, the operator function yields x <=> y @ 0 if an operator<=> with the original order of parameters was selected, or 0 @ y <=> x otherwise.
struct C {
  friend std::strong_equality operator<=>(const C&, const C&);
  friend bool operator==(const C& x, const C& y) = default; // OK, returns x <=> y == 0
  bool operator<(const C&) = default;                       // OK, function is deleted
end example