常用算术转换
来自 cppreference.com
许多需要 算术 或 枚举 类型的操作数的二元运算符会导致转换并以类似的方式生成结果类型。其目的是生成一个公共类型,这也是结果的类型。这种模式称为常用算术转换。
内容 |
[编辑] 定义
常用算术转换定义如下
[编辑] 阶段 1
将 左值转换为右值转换 应用于两个操作数,生成的右值在剩余流程中用于代替原始操作数。
[编辑] 阶段 2
|
(自 C++11 起) |
[编辑] 阶段 3
|
(自 C++26 起) |
[编辑] 阶段 4
- 如果任一操作数是 浮点类型,则应用以下规则
- 如果两个操作数具有相同的类型,则不会执行进一步的转换。
- 否则,如果一个操作数是非浮点类型,则该操作数将转换为另一个操作数的类型。
- 否则,如果操作数类型的 浮点转换等级 排序但(自 C++23 起) 不相等,则类型具有较低浮点转换等级的操作数将转换为另一个操作数的类型。
|
(自 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
相对应的无符号整型。
- 如果
如果一个操作数是枚举类型,而另一个操作数是不同的枚举类型或浮点类型,则此行为已弃用。 |
(自 C++20 起) (直到 C++26) |
[编辑] 整型转换等级
每个 整型 都具有一个整型转换等级,定义如下。
- 除了 char 和 signed char(如果 char 是有符号的)之外,没有两个有符号整型具有相同的等级,即使它们具有相同的表示。
- 有符号整型的等级高于任何宽度更小的有符号整型的等级。
- 以下整型的等级按顺序递减。
|
(自 C++11 起) |
- long
- int
- short
- signed char
- 任何无符号整型的等级都等于相应有符号整型的等级。
|
(自 C++11 起) |
- bool 的等级低于所有标准整型的等级。
- 编码字符类型(char , char8_t(自 C++20 起), char16_t, char32_t,(自 C++11 起) 和 wchar_t)的等级等于其 底层类型 的等级,这意味着。
- char 的等级等于 signed char 和 unsigned char 的等级。
|
(自 C++20 起) |
|
(自 C++11 起) |
- wchar_t 的等级等于其实现定义的底层类型的等级。
|
(自 C++11 起) |
- 对于所有整型
T1
、T2
和T3
,如果T1
的等级高于T2
,而T2
的等级高于T3
,则T1
的等级高于T3
。
整型转换等级也用于 整型提升 的定义中。
[编辑] 浮点转换等级和子等级
[编辑] 浮点转换等级
每个 浮点类型 都具有一个浮点转换等级,定义如下。
- 标准浮点类型的等级按顺序递减。
- long double
- double
- float
|
(自 C++23 起) |
浮点转换子等级具有相同浮点转换等级的浮点类型按浮点转换子等级排序。子等级在具有相同等级的类型之间形成一个全序。 类型 |
(自 C++23 起) |
[编辑] 使用
浮点转换等级和子等级也用于
- 确定不同浮点类型之间的转换是否可以是隐式的或是否是窄化转换,
- 区分重载解析中的转换序列,
|
(自 C++23 起) |
- 确定 std::complex 的 转换构造函数 是显式的,还是
- 确定如果不同浮点类型的参数传递给 通用 或 特殊 数学函数,则公共浮点类型。
[编辑] 缺陷报告
以下更改行为的缺陷报告被追溯应用于之前发布的 C++ 标准。
DR | 应用于 | 已发布的行为 | 正确行为 |
---|---|---|---|
CWG 1642 | C++98 | 通常的算术转换可能涉及左值 | 首先应用左值到右值转换 |
CWG 2528 | C++20 | unsigned char 之间的三个方向比较 和 unsigned int 是格式错误的,因为 中间的整型提升[1] |
根据 提升后的类型确定公共类型,而没有 实际提升操作数[2] |
CWG 2892 | C++98 | 当两个操作数都是相同类型 的浮点数时,“不需要 进一步转换”的含义不清楚 |
更改为“不会进行进一步 转换” |