Files
cppdraft_translate/cppdraft/class/compare.md
2025-10-25 03:02:53 +03:00

337 lines
15 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[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.3Binary 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.2Explicitly-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.1General[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.2Anonymous 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.1Defaulted 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.2Overload 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.1General[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.1General[class.mem.general]"),
with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[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.1General[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.6Functions[dcl.fct]") and
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[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.5Exception specifications[except.spec]"),
the implicitly-declared == operator function
has an implicit exception specification ([[except.spec]](except.spec "14.5Exception 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<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](#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.1General[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.1General[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.2Implicit conversion sequences")),
class member access expressions ([[expr.ref]](expr.ref "7.6.1.5Class member access")), and
array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2Subscripting")) 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.3Binary 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.1Defaulted 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.3Three-way comparison[class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2Comparison 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.1Defaulted comparison operator functions")) and
can be explicitly converted to R using static_cast,static_cast<R>(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.1Preamble")) 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<R>(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.3Three-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.2Class 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.3Class 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.4Class 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.4Secondary comparison operators[class.compare.secondary]") is
a relational operator ([[expr.rel]](expr.rel "7.6.9Relational operators")) or the != operator[.](#secondary-1.sentence-1)
A defaulted operator function ([[over.binary]](over.binary "12.4.3Binary 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.2Overload 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.3Operators 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*]