Usual arithmetic conversions
Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions
Definition
Usual arithmetic conversions are defined as follows:
Stage 1
Applies lvalue-to-rvalue conversion
Stage 2
|
(since C++11) |
Stage 3
|
(since C++26) |
Stage 4
- If either operand is of floating-point type, the following rules are applied:
-
- If both operands have the same type, no further conversion will be performed.
- Otherwise, if one of the operands is of a non-floating-point type, that operand is converted to the type of the other operand.
- Otherwise, if the floating-point conversion ranks of the types of the operands are ordered but (since C++23)
|
(since C++23) |
- Otherwise, both operands are of integer types, proceed to the next stage.
Stage 5
Both operands are converted to a common type C
. Given the types T1
and T2
as the promoted type (under the rules of integral promotions) of the operands, the following rules are applied to determine C
- If
T1
andT2
are the same type,C
is that type. - Otherwise, if
T1
andT2
are both signed integer types or both unsigned integer types,C
is the type of greater integer conversion rank - Otherwise, one type between
T1
andT2
is an signed integer typeS
, the other type is an unsigned integer typeU
. Apply the following rules:
-
- If the integer conversion rank of
U
is greater than or equal to the integer conversion rank ofS
,C
isU
. - Otherwise, if
S
can represent all of the values ofU
,C
isS
. - Otherwise,
C
is the unsigned integer type corresponding toS
.
- If the integer conversion rank of
If one operand is of enumeration type and the other operand is of a different enumeration type or a floating-point type, this behavior is deprecated. |
(since C++20) (until C++26) |
Integer conversion rank
Every integer type has an integer conversion rank defined as follows:
- No two signed integer types other than char and signed char (if char
- The rank of a signed integer type is greater than the rank of any signed integer type with a smaller width.
- The ranks of the following integer types decrease in order:
|
(since C++11) |
-
- long
- int
- short
- signed char
- The rank of any unsigned integer type equals the rank of the corresponding signed integer type.
|
(since C++11) |
- The rank of bool is less than the rank of all standard integer types.
- The ranks of encoding character types (char , char8_t(since C++20) , char16_t, char32_t, (since C++11) and wchar_t) equal the ranks of their underlying types
-
- The rank of char equals the rank of signed char and unsigned char
|
(since C++20) |
|
(since C++11) |
- The rank of wchar_t equals the rank of its implementation-defined underlying type.
|
(since C++11) |
- For all integer types
T1
,T2
, andT3
, ifT1
has greater rank thanT2
andT2
has greater rank thanT3
, thenT1
has greater rank thanT3
The integer conversion rank is also used in the definition of integral promotion.
Floating-point conversion rank and subrank
Floating-point conversion rank
Every floating-point type has a floating-point conversion rank defined as follows:
- The ranks of the standard floating-point types decrease in order:
- long double
- double
- float
|
(since C++23) |
Floating-point conversion subrankFloating-point types that have equal floating-point conversion ranks are ordered by floating-point conversion subrank. The subrank forms a total order among types with equal ranks. The types |
(since C++23) |
Usage
The floating-point conversion rank and subrank are also used to
- determine whether a conversion between different floating-point types can be implicit or is a narrowing conversion
- distinguish the conversion sequences in overload resolution,
|
(since C++23) |
- determine whether std::complex's converting constructor
- determine the common floating-point type if the arguments of different floating-point types are passed to common or special
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1642 | C++98 | usual arithmetic conversions might involve lvalues | applies lvalue-to-rvalue conversions first |
CWG 2528 | C++20 | the three-way comparison between unsigned char
and unsigned int is ill-formed because of the intermediate integral promotion[1] |
determines the common type based on the promoted types, without actually promoting the operands[2] |
CWG 2892 | C++98 | when both operands are of the same floating-point type, the meaning of “no further conversion is needed” was unclear |
changed to “no further conversion will be performed” |