[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 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)