[expr.spaceship]

# 7 Expressions [[expr]](./#expr)

## 7.6 Compound expressions [[expr.compound]](expr.compound#expr.spaceship)

### 7.6.8 Three-way comparison operator [expr.spaceship]

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7283)

The three-way comparison operator groups left-to-right[.](#1.sentence-1)

[compare-expression:](#nt:compare-expression "7.6.8 Three-way comparison operator [expr.spaceship]")  
[*shift-expression*](expr.shift#nt:shift-expression "7.6.7 Shift operators [expr.shift]")  
[*compare-expression*](#nt:compare-expression "7.6.8 Three-way comparison operator [expr.spaceship]") <=> [*shift-expression*](expr.shift#nt:shift-expression "7.6.7 Shift operators [expr.shift]")

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7296)

The expression p <=> q is a prvalue indicating whetherp is less than, equal to, greater than, or incomparable withq[.](#2.sentence-1)

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7301)

If one of the operands is of type bool and the other is not, the program is ill-formed[.](#3.sentence-1)

[4](#4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7305)

If both operands have arithmetic types,
or one operand has integral type and
the other operand has unscoped enumeration type,
the [usual arithmetic conversions](expr.arith.conv "7.4 Usual arithmetic conversions [expr.arith.conv]") are applied to the operands[.](#4.sentence-1)

Then:

- [(4.1)](#4.1)

  If a [narrowing conversion](dcl.init.list#def:conversion,narrowing "9.5.5 List-initialization [dcl.init.list]") is required,
other than from an integral type to a floating-point type,
the program is ill-formed[.](#4.1.sentence-1)

- [(4.2)](#4.2)

  Otherwise, if the operands have integral type,
the result is of type std​::​strong_ordering[.](#4.2.sentence-1)
  The result isstd​::​strong_ordering​::​equal if both operands are arithmetically equal,std​::​strong_ordering​::​less if the first operand is arithmetically
less than the second operand,
andstd​::​strong_ordering​::​greater otherwise[.](#4.2.sentence-2)

- [(4.3)](#4.3)

  Otherwise, the operands have floating-point type, and
the result is of type std​::​partial_ordering[.](#4.3.sentence-1)
  The expression a <=> b yieldsstd​::​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,
andstd​::​partial_ordering​::​unordered otherwise[.](#4.3.sentence-2)

[5](#5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7343)

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[.](#5.sentence-1)

[6](#6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7349)

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]](conv.array "7.3.3 Array-to-pointer conversion")),
pointer conversions ([[conv.ptr]](conv.ptr "7.3.12 Pointer conversions")),
and[qualification conversions](conv.qual "7.3.6 Qualification conversions [conv.qual]") are performed on both operands
to bring them to their composite pointer type ([[expr.type]](expr.type "7.2.2 Type"))[.](#6.sentence-1)

After the conversions, the operands shall have the same type[.](#6.sentence-2)

[*Note [1](#note-1)*:

If both of the operands are arrays,[array-to-pointer conversions](conv.array "7.3.3 Array-to-pointer conversion [conv.array]") are not applied[.](#6.sentence-3)

â *end note*]

In this case,p <=> q is of type std​::​strong_ordering and
the result is defined by the following rules:

- [(6.1)](#6.1)

If two pointer operands p and q compare equal ([[expr.eq]](expr.eq "7.6.10 Equality operators")),p <=> q yields std​::​strong_ordering​::​equal;

- [(6.2)](#6.2)

otherwise, if p and q compare unequal,p <=> q yieldsstd​::​strong_ordering​::​less if q compares greater than p andstd​::​strong_ordering​::​greater if p compares greater than q ([[expr.rel]](expr.rel "7.6.9 Relational operators"));

- [(6.3)](#6.3)

otherwise, the result is unspecified[.](#6.sentence-4)

[7](#7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7382)

Otherwise, the program is ill-formed[.](#7.sentence-1)

[8](#8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/expressions.tex#L7385)

The three comparison category types ([[cmp.categories]](cmp.categories "17.12.2 Comparison category types"))
(the typesstd​::​strong_ordering,std​::​weak_ordering, andstd​::​partial_ordering)
are not predefined;
if a standard library declaration ([[compare.syn]](compare.syn "17.12.1 Header <compare> synopsis"), [[std.modules]](std.modules "16.4.2.4 Modules"))
of such a class type does not precede ([[basic.lookup.general]](basic.lookup.general "6.5.1 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]](dcl.spec.auto "9.2.9.7 Placeholder type specifiers"))
in a defaulted three-way comparison ([[class.spaceship]](class.spaceship "11.10.3 Three-way comparison"))
or use of the built-in operator) â the program is ill-formed[.](#8.sentence-1)
