Title
Three-way comparison and the usual arithmetic conversions
Status
c++23
Section
7.4 [expr.arith.conv]
Submitter
Cameron DaCamara

Created on 2022-01-26.00:00:00 last changed 16 months ago

Messages

Date: 2023-02-10.03:08:38

Proposed resolution (approved by CWG 2023-02-09):

Change in 7.4 [expr.arith.conv] bullet 1.3 as follows, adding sub-bullets:

Otherwise, the integral promotions (7.3.7 [conv.prom]) are performed on both operands each operand is converted to a common type C. The integral promotion rules (7.3.7 [conv.prom]) are used to determine a type T1 and type T2 for each operand. [ Footnote: ... ] Then the following rules are applied to the promoted operands determine C:
  • If both operands have T1 and T2 are the same type, no further conversion is needed C is that type.
  • Otherwise, if T1 and T2 are both operands have signed integer types or are both have unsigned integer types, the operand with the type of lesser integer conversion rank is converted to the type of the operand C is the type with greater rank.
  • Otherwise, if the operand that has let U be the unsigned integer type and S be the signed integer type.
    • If U has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type S, C is U.
    • Otherwise, if the type of the operand with signed integer type S can represent all of the values of the type of the operand with unsigned integer type, the operand with unsigned integer type is converted to the type of the operand with signed integer type U, C is S.
    • Otherwise, both operands are converted to C is the unsigned integer type corresponding to the type of the operand with signed integer type S.
Date: 2023-02-10.03:08:38

Suggested resolution [SUPERSEDED]:

Change 7.4 [expr.arith.conv] bullet 1.5 as follows:

Otherwise, the integral promotions (7.3.7 [conv.prom]) shall be performed on both operands each operand shall be converted to a common type C. The integral promotion rules (7.3.7 [conv.prom] shall be used to determine a type T1 and type T2 for each operand.50 Then the following rules shall be applied to the promoted operands determine C:

  • If both operands have T1 and T2 are the same type, no further conversion is needed C shall be that type.

  • Otherwise, if both operands have T1 and T2 are both signed integer types or both have are unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand C shall be the type with greater rank.

  • Otherwise, if the operand that has the type U that is an unsigned integer type has rank greater than or equal to the rank of the other type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type, C shall be U.

  • Otherwise, if the type of the operand with S that is a signed integer type can represent all of the values of the other type of the operand with unsigned integer type, the operand with unsigned integer type shall be converted to the type of the operand with signed integer type, C shall be S.

  • Otherwise, both operands shall be converted to C shall be the unsigned integer type corresponding to the type of the operand with signed integer type.

Date: 2023-02-15.00:00:00

[Accepted as a DR at the February, 2023 meeting.]

Consider an example like:

  void f(unsigned char i, unsigned ui) {
    i <=> ui;
  }

According to 7.6.8 [expr.spaceship] paragraph 4, the usual arithmetic conversions are applied to the operands. According to 7.4 [expr.arith.conv] bullet 1.5, the integral promotions are performed on both operands, resulting in i being converted from unsigned char to int. The operands are then of types int and unsigned int, so bullet 1.5.5 applies, further converting i to type unsigned int.

Unfortunately, that latter conversion, from int to unsigned int, is a narrowing conversion, which runs afoul of 7.6.8 [expr.spaceship] bullet 4.1, which prohibits narrowing conversions other than integral to floating in three-way comparisons.

History
Date User Action Args
2023-07-16 13:00:43adminsetstatus: open -> c++23
2023-07-16 13:00:43adminsetstatus: dr -> open
2023-02-18 18:43:04adminsetstatus: ready -> dr
2023-02-10 23:01:52adminsetstatus: tentatively ready -> ready
2023-02-10 03:08:38adminsetmessages: + msg7182
2023-02-10 03:08:38adminsetstatus: drafting -> tentatively ready
2022-11-20 07:54:16adminsetstatus: open -> drafting
2022-02-18 07:47:23adminsetmessages: + msg6728
2022-01-26 00:00:00admincreate