#
A defaulted comparison operator function ([over.binary]) shall be a non-template function that
Such a comparison operator function is termed a defaulted comparison operator function for class C.
Name lookups and access checks in the implicit definition ([dcl.fct.def.default]) of a comparison operator function are performed from a context equivalent to its function-body.
A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function.
[Example 1: struct S; bool operator=(S, S) = default; / error: S is not complete struct S { friend bool operator=(S, const S&) = default; / error: parameters of different types }; enum E { }; bool operator=(E, E) = default; / error: not a member or friend of a class — end example]
A defaulted <=> or == operator function for class C is defined as deleted if any non-static data member of C is of reference type or C has variant members ([class.union.anon]).
A binary operator expression a @ b is usable if either
  • a or b is of class or enumeration type and overload resolution ([over.match]) as applied to a @ b results in a usable candidate, or
  • neither a nor b is of class or enumeration type and a @ b is a valid expression.
If the member-specification does not explicitly declare any member or friend named operator=, an == operator function is declared implicitly for each three-way comparison operator function defined as defaulted in the member-specification, with the same access and function-definition and in the same class scope as the respective three-way comparison operator function, except that the return type is replaced with bool and the declarator-id is replaced with operator=.
[Note 1: 
Such an implicitly-declared == operator for a class X is defined as defaulted in the definition of X and has the same parameter-declaration-clause and trailing requires-clause as the respective three-way comparison operator.
It is declared with friend, virtual, constexpr, or consteval if the three-way comparison operator function is so declared.
If the three-way comparison operator function has no noexcept-specifier, the implicitly-declared == operator function has an implicit exception specification ([except.spec]) that can differ from the implicit exception specification of the three-way comparison operator function.
— end note]
[Example 2: template<typename T> struct X { friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default; / implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default; [[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default; / implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default; }; — end example]
[Note 2: 
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

11.10.2 Equality operator [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
The return value of a defaulted == operator function with parameters x and y is determined by comparing corresponding elements
The return value is false if such an index exists and true otherwise.
[Example 1: struct D { int i; friend bool operator=(const D& x, const D& y) = default; / OK, returns x.i == y.i }; — end example]

11.10.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 a <=> b is usable ([class.compare.default]) and can be explicitly converted to R using static_cast, static_cast<R>(a <=> b).
  • Otherwise, if a <=> b is usable or overload resolution for a <=> b is performed and finds at least one viable candidate, the synthesized three-way comparison is not defined.
  • Otherwise, if R is not a comparison category type, or either the expression a == b or the expression a < b is not usable, 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 (when R is partial_ordering), a == b ? partial_ordering::equivalent : a < b ? partial_ordering::less : b < a ? partial_ordering::greater : partial_ordering::unordered
[Note 1: 
A synthesized three-way comparison is ill-formed if overload resolution finds usable candidates 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, and let
  • If R is auto, then let
    The operator function is defined as deleted if that expression is not usable or if
    The return type is deduced as the common comparison type (see below) of
  • Otherwise, R shall not contain a placeholder type.
    If the synthesized three-way comparison of type R between any objects
The return value 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
The return value is a copy of
The common comparison type U of a possibly-empty list of n comparison category types

11.10.4 Secondary comparison operators [class.compare.secondary]

A secondary comparison operator is a relational operator ([expr.rel]) or the != operator.
A defaulted operator function ([over.binary]) for a secondary comparison operator @ shall have a declared return type bool.
The operator function with parameters x and y is defined as deleted if
  • a first overload resolution ([over.match]), as applied to x @ y,
    • does not result in a usable candidate, or
    • the selected candidate is not a rewritten candidate, or
  • a second overload resolution for the expression resulting from the interpretation of x @ y using the selected rewritten candidate ([over.match.oper]) does not result in a usable candidate (for example, that expression might be (x <=> y) @ 0), or
  • x @ y cannot be implicitly converted to bool.
In any of the two overload resolutions above, the defaulted operator function is not considered as a candidate for the @ operator.
Otherwise, the operator function yields x @ y.
[Example 1: struct HasNoLessThan { }; struct C { friend HasNoLessThan operator<=>(const C&, const C&); bool operator<(const C&) const = default; / OK, function is deleted }; — end example]

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant