Usual arithmetic conversions
许多期望操作数为 算术 类型或 枚举 类型的二元运算符会以类似方式引发类型转换并生成结果类型。其目的是产生一个公共类型,该类型同时也是结果的类型。这种模式被称为 常规算术转换 。
目录 |
定义
通常的算术转换定义如下:
第一阶段
对两个操作数应用 左值到右值转换 ,生成的纯右值将在后续处理过程中替代原始操作数。
阶段 2
|
(since C++11) |
阶段 3
|
(since C++26) |
阶段 4
- 如果任一操作数为 浮点类型 ,则应用以下规则:
-
- 若两操作数类型相同,则不进行进一步转换。
- 否则,若任一操作数为非浮点类型,则该操作数被转换为另一操作数的类型。
- 否则,若操作数类型的 浮点转换等级 存在有序关系但不相等 (C++23 起) ,则浮点转换等级较低的操作数类型被转换为另一操作数的类型。
|
(since C++23) |
- 否则,两个操作数均为整数类型,进入下一阶段。
阶段 5
两个操作数都会被转换为一个公共类型
C
。将提升后的操作数类型分别记为
T1
和
T2
(
遵循整型提升规则
),以下规则将用于确定
C
:
-
若
T1与T2类型相同,则C为该类型。 -
否则,若
T1与T2均为有符号整数类型或均为无符号整数类型,则C为具有更高 整数转换等级 的类型。 -
否则,若
T1与T2中一者为有符号整数类型S,另一者为无符号整数类型U。应用以下规则:
-
-
若
U的整数转换等级大于或等于S的整数转换等级,则C为U。 -
否则,若
S能表示U的所有值,则C为S。 -
否则,
C为与S对应的无符号整数类型。
-
若
|
如果一个操作数是枚举类型,另一个操作数是不同的枚举类型或浮点类型,此行为已被弃用。 |
(since C++20)
(until C++26) |
整数转换等级
每个 整数类型 都具有按如下方式定义的 整数转换等级 :
- 除了 char 和 signed char (若 char 为有符号类型)之外,没有两个有符号整数类型具有相同等级,即使它们具有相同的表示形式。
- 有符号整数类型的等级大于任何宽度更小的有符号整数类型的等级。
- 下列整数类型的等级按顺序递减:
|
(自 C++11 起) |
-
- long
- int
- short
- signed char
- 任何无符号整数类型的等级等于对应的有符号整数类型的等级。
|
(since C++11) |
- bool 的等级低于所有标准整数类型的等级。
- 编码字符类型( char 、 char8_t (C++20 起) 、 char16_t 、 char32_t 、 (C++11 起) 和 wchar_t )的等级等于其 底层类型 的等级,这意味着:
-
- char 的等级等于 signed char 和 unsigned char 的等级。
|
(since C++20) |
|
(since C++11) |
-
- wchar_t 的等级等于其实现定义的底层类型的等级。
|
(since C++11) |
-
对于所有整数类型
T1、T2和T3,若T1的等级高于T2且T2的等级高于T3,则T1的等级高于T3。
整数转换等级也用于 整型提升 的定义。
浮点转换等级与子等级
浮点转换等级
每个 浮点类型 都具有按如下方式定义的 浮点转换等级 :
-
标准浮点类型的等级按以下顺序递减:
- long double
- double
- float
|
(since C++23) |
浮点转换子级具有相同浮点转换等级的浮点类型通过 浮点转换子级 进行排序。该子级在具有相同等级的类型间形成全序关系。
类型
|
(since C++23) |
用法
浮点转换等级和子等级也用于
|
(since C++23) |
- 确定 std::complex 的 转换构造函数 是否为显式声明,或
- 当向 通用 或 特殊 数学函数传递不同浮点类型的参数时,确定其公共浮点类型。
缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的C++标准。
| 缺陷报告 | 适用标准 | 发布时行为 | 正确行为 |
|---|---|---|---|
| CWG 1642 | C++98 | 常规算术转换可能涉及左值 | 先应用左值到右值转换 |
| CWG 2528 | C++20 |
unsigned
char
与
unsigned
int
的三路比较因
中间整型提升而格式错误 [1] |
基于提升后的类型确定公共类型,
但不实际提升操作数 [2] |
| CWG 2892 | C++98 |
当两个操作数均为相同浮点类型时,
“无需进一步转换”的含义不明确 |
改为“不会执行进一步转换” |