7 Expressions [expr]

7.6 Compound expressions [expr.compound]

7.6.8 Three-way comparison operator [expr.spaceship]

The three-way comparison operator groups left-to-right.
The expression p <=> q is a prvalue indicating whether p is less than, equal to, greater than, or incomparable with q.
If one of the operands is of type bool and the other is not, the program is ill-formed.
If both operands have arithmetic types, or one operand has integral type and the other operand has unscoped enumeration type, the usual arithmetic conversions are applied to the operands.
Then:
  • If a narrowing conversion is required, other than from an integral type to a floating-point type, the program is ill-formed.
  • Otherwise, if the operands have integral type, the result is of type std​::​strong_ordering.
    The result is std​::​strong_ordering​::​equal if both operands are arithmetically equal, std​::​strong_ordering​::​less if the first operand is arithmetically less than the second operand, and std​::​strong_ordering​::​greater otherwise.
  • Otherwise, the operands have floating-point type, and the result is of type std​::​partial_ordering.
    The expression a <=> b yields std​::​partial_ordering​::​less if a is less than b, std​::​partial_ordering​::​greater if a is greater than b, std​::​partial_ordering​::​equivalent if a is equivalent to b, and std​::​partial_ordering​::​unordered otherwise.
If both operands have the same enumeration type E, the operator yields the result of converting the operands to the underlying type of E and applying <=> to the converted operands.
If at least one of the operands is of object pointer type and the other operand is of object pointer or array type, array-to-pointer conversions ([conv.array]), pointer conversions ([conv.ptr]), and qualification conversions are performed on both operands to bring them to their composite pointer type ([expr.type]).
After the conversions, the operands shall have the same type.
[Note 1: 
If both of the operands are arrays, array-to-pointer conversions are not applied.
— end note]
In this case, p <=> q is of type std​::​strong_ordering and the result is defined by the following rules:
  • If two pointer operands p and q compare equal ([expr.eq]), p <=> q yields std​::​strong_ordering​::​equal;
  • otherwise, if p and q compare unequal, p <=> q yields std​::​strong_ordering​::​less if q compares greater than p and std​::​strong_ordering​::​greater if p compares greater than q ([expr.rel]);
  • otherwise, the result is unspecified.
Otherwise, the program is ill-formed.
The three comparison category types ([cmp.categories]) (the types std​::​strong_ordering, std​::​weak_ordering, and std​::​partial_ordering) are not predefined; if a standard library declaration ([compare.syn], [std.modules]) of such a class type does not precede ([basic.lookup.general]) a use of that type — even an implicit use in which the type is not named (e.g., via the auto specifier ([dcl.spec.auto]) in a defaulted three-way comparison ([class.spaceship]) or use of the built-in operator) — the program is ill-formed.