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.
compare-expression:
	shift-expression
	compare-expression <=> shift-expression
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 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 pointer type and the other operand is of 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
:
If both of the operands are arrays, array-to-pointer conversions are not applied.
— end note
 ]
If the composite pointer type is an object pointer type, p <=> q is of type std​::​strong_­ordering.
If two pointer operands p and q compare equal ([expr.eq]), p <=> q yields std​::​strong_­ordering​::​equal; 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 the header <compare> ([compare.syn]) is not imported or included prior to a use of such a class type – even an implicit use in which the type is not named (e.g., via the auto specifier in a defaulted three-way comparison or use of the built-in operator) – the program is ill-formed.