[class.compare] # 11 Classes [[class]](./#class) ## 11.10 Comparisons [class.compare] ### [11.10.1](#default) Defaulted comparison operator functions [[class.compare.default]](class.compare.default) [1](#default-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6562) A defaulted comparison operator function ([[over.binary]](over.binary "12.4.3 Binary operators")) shall be a non-template function that - [(1.1)](#default-1.1) is a non-static member or friend of some class C, - [(1.2)](#default-1.2) is defined as defaulted in C or in a context where C is complete, and - [(1.3)](#default-1.3) either has two parameters of type const C& or two parameters of type C, where the implicit object parameter (if any) is considered to be the first parameter[.](#default-1.sentence-1) Such a comparison operator function is termeda defaulted comparison operator function for class C[.](#default-1.sentence-2) Name lookups and access checks in the implicit definition ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")) of a comparison operator function are performed from a context equivalent to its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1 General [dcl.fct.def.general]")[.](#default-1.sentence-3) A definition of a comparison operator as defaulted that appears in a class shall be the first declaration of that function[.](#default-1.sentence-4) [*Example [1](#default-example-1)*: struct S;bool operator==(S, S) = default; // error: S is not completestruct 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*] [2](#default-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6604) A defaulted <=> or == operator function for class Cis defined as deleted if any non-static data member of C is of reference type orC has variant members ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions"))[.](#default-2.sentence-1) [3](#default-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6612) A binary operator expression a @ b is[*usable*](#def:usable,binary_operator_expression "11.10.1 Defaulted comparison operator functions [class.compare.default]") if either - [(3.1)](#default-3.1) a or b is of class or enumeration type and overload resolution ([[over.match]](over.match "12.2 Overload resolution")) as applied to a @ b results in a usable candidate, or - [(3.2)](#default-3.2) neither a nor b is of class or enumeration type anda @ b is a valid expression[.](#default-3.sentence-1) [4](#default-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6627) If the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") 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*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]"), with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]") 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*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") is replaced with operator==[.](#default-4.sentence-1) [*Note [1](#default-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*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") and trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") as the respective three-way comparison operator[.](#default-4.sentence-2) It is declared with friend, virtual, constexpr, or consteval if the three-way comparison operator function is so declared[.](#default-4.sentence-3) If the three-way comparison operator function has no [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]"), the implicitly-declared == operator function has an implicit exception specification ([[except.spec]](except.spec "14.5 Exception specifications")) that can differ from the implicit exception specification of the three-way comparison operator function[.](#default-4.sentence-4) — *end note*] [*Example [2](#default-example-2)*: template 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](#default-note-2)*: The == operator function is declared implicitly even if the defaulted three-way comparison operator function is defined as deleted[.](#default-4.sentence-5) — *end note*] [5](#default-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6673) The direct base class subobjects of C, in the order of their declaration in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [class.derived.general]") of C, followed by the non-static data members of C, in the order of their declaration in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of C, form a list of subobjects[.](#default-5.sentence-1) In that list, any subobject of array type is recursively expanded to the sequence of its elements, in the order of increasing subscript[.](#default-5.sentence-2) Let xi be an lvalue denoting the ith element in the expanded list of subobjects for an object x (of length n), where xi is formed by a sequence of derived-to-base conversions ([[over.best.ics]](over.best.ics "12.2.4.2 Implicit conversion sequences")), class member access expressions ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), and array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")) applied to x[.](#default-5.sentence-3) ### [11.10.2](#class.eq) Equality operator [[class.eq]](class.eq) [1](#class.eq-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6693) A defaulted equality operator function ([[over.binary]](over.binary "12.4.3 Binary operators")) shall have a declared return type bool[.](#class.eq-1.sentence-1) [2](#class.eq-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6697) A defaulted == operator function for a class C is defined as deleted unless, for each xi in the expanded list of subobjects for an object x of type C,xi == xi is usable ([[class.compare.default]](#default "11.10.1 Defaulted comparison operator functions"))[.](#class.eq-2.sentence-1) [3](#class.eq-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6705) The return value of a defaulted == operator function with parameters x and y is determined by comparing corresponding elements xi and yi in the expanded lists of subobjects for x and y (in increasing index order) until the first index i where xi == yi yields a result value which, when contextually converted to bool, yields false[.](#class.eq-3.sentence-1) The return value is false if such an index exists and true otherwise[.](#class.eq-3.sentence-2) [4](#class.eq-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6717) [*Example [1](#class.eq-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](#class.spaceship) Three-way comparison [[class.spaceship]](class.spaceship) [1](#class.spaceship-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6731) The [*synthesized three-way comparison*](#def:three-way_comparison,synthesized "11.10.3 Three-way comparison [class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2 Comparison category types")) of glvalues a and b of the same type is defined as follows: - [(1.1)](#class.spaceship-1.1) If a <=> b is usable ([[class.compare.default]](#default "11.10.1 Defaulted comparison operator functions")) and can be explicitly converted to R using static_cast,static_cast(a <=> b)[.](#class.spaceship-1.1.sentence-1) - [(1.2)](#class.spaceship-1.2) 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[.](#class.spaceship-1.2.sentence-1) - [(1.3)](#class.spaceship-1.3) 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[.](#class.spaceship-1.3.sentence-1) - [(1.4)](#class.spaceship-1.4) Otherwise, if R is strong_ordering, thena == b ? strong_ordering::equal : a < b ? strong_ordering::less : strong_ordering::greater - [(1.5)](#class.spaceship-1.5) Otherwise, if R is weak_ordering, thena == b ? weak_ordering::equivalent : a < b ? weak_ordering::less : weak_ordering::greater - [(1.6)](#class.spaceship-1.6) 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](#class.spaceship-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[.](#class.spaceship-1.sentence-2) — *end note*] [2](#class.spaceship-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6786) Let R be the declared return type of a defaulted three-way comparison operator function, and let xi be the elements of the expanded list of subobjects for an object x of type C[.](#class.spaceship-2.sentence-1) - [(2.1)](#class.spaceship-2.1) If R is auto, then let cvi Ri be the type of the expression xi <=> xi[.](#class.spaceship-2.1.sentence-1) The operator function is defined as deleted if that expression is not usable or if Ri is not a comparison category type ([[cmp.categories.pre]](cmp.categories.pre "17.12.2.1 Preamble")) for any i[.](#class.spaceship-2.1.sentence-2) The return type is deduced as the common comparison type (see below) ofR0, R1, …, Rn−1[.](#class.spaceship-2.1.sentence-3) - [(2.2)](#class.spaceship-2.2) Otherwise, R shall not contain a placeholder type[.](#class.spaceship-2.2.sentence-1) If the synthesized three-way comparison of type R between any objects xi and xi is not defined, the operator function is defined as deleted[.](#class.spaceship-2.2.sentence-2) [3](#class.spaceship-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6813) 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 elementsxi and yi 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 xi and yi yields a result value vi where vi!=0, contextually converted to bool, yields true[.](#class.spaceship-3.sentence-1) The return value is a copy of vi if such an index exists andstatic_cast(std​::​strong_ordering​::​equal) otherwise[.](#class.spaceship-3.sentence-2) [4](#class.spaceship-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6830) The [*common comparison type*](#def:common_comparison_type "11.10.3 Three-way comparison [class.spaceship]") U of a possibly-empty list of n comparison category typesT0, T1, …, Tn−1 is defined as follows: - [(4.1)](#class.spaceship-4.1) If at least one Ti is std​::​partial_ordering,U is std​::​partial_ordering ([[cmp.partialord]](cmp.partialord "17.12.2.2 Class partial_­ordering"))[.](#class.spaceship-4.1.sentence-1) - [(4.2)](#class.spaceship-4.2) Otherwise, if at least one Ti is std​::​weak_ordering,U is std​::​weak_ordering ([[cmp.weakord]](cmp.weakord "17.12.2.3 Class weak_­ordering"))[.](#class.spaceship-4.2.sentence-1) - [(4.3)](#class.spaceship-4.3) Otherwise, U is std​::​strong_ordering ([[cmp.strongord]](cmp.strongord "17.12.2.4 Class strong_­ordering"))[.](#class.spaceship-4.3.sentence-1) [*Note [2](#class.spaceship-note-2)*: In particular, this is the result when n is 0[.](#class.spaceship-4.3.sentence-2) — *end note*] ### [11.10.4](#secondary) Secondary comparison operators [[class.compare.secondary]](class.compare.secondary) [1](#secondary-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6855) A [*secondary comparison operator*](#def:secondary_comparison_operator "11.10.4 Secondary comparison operators [class.compare.secondary]") is a relational operator ([[expr.rel]](expr.rel "7.6.9 Relational operators")) or the != operator[.](#secondary-1.sentence-1) A defaulted operator function ([[over.binary]](over.binary "12.4.3 Binary operators")) for a secondary comparison operator @ shall have a declared return type bool[.](#secondary-1.sentence-2) [2](#secondary-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6863) The operator function with parameters x and y is defined as deleted if - [(2.1)](#secondary-2.1) a first overload resolution ([[over.match]](over.match "12.2 Overload resolution")), as applied to x @ y, * [(2.1.1)](#secondary-2.1.1) does not result in a usable candidate, or * [(2.1.2)](#secondary-2.1.2) the selected candidate is not a rewritten candidate, or - [(2.2)](#secondary-2.2) a second overload resolution for the expression resulting from the interpretation of x @ y using the selected rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3 Operators in expressions")) does not result in a usable candidate (for example, that expression might be (x <=> y) @ 0), or - [(2.3)](#secondary-2.3) x @ y cannot be implicitly converted to bool[.](#secondary-2.sentence-1) In any of the two overload resolutions above, the defaulted operator function is not considered as a candidate for the @ operator[.](#secondary-2.sentence-2) Otherwise, the operator function yields x @ y[.](#secondary-2.sentence-3) [3](#secondary-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6892) [*Example [1](#secondary-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*]