常用算术转换
来自 cppreference.cn
许多期待算术或枚举类型操作数的二元运算符,会以类似的方式引发转换并产生结果类型。其目的是产生一个公共类型,该类型也是结果的类型。此模式被称为常规算术转换(usual arithmetic conversions)。
目录 |
[编辑] 定义
常规算术转换定义如下
[编辑] 阶段 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) |
[编辑] 整数转换等级
每个整数类型都有一个整数转换等级(integer conversion rank),定义如下
- 除了 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
。
整数转换等级也用于整数提升的定义中。
[编辑] 浮点转换等级和次等级
[编辑] 浮点转换等级
每个浮点类型都有一个浮点转换等级(floating-point conversion rank),定义如下
- 标准浮点类型的等级依次降低
- long double
- double
- float
|
(C++23 起) |
浮点转换次等级浮点转换等级相等的浮点类型,通过浮点转换次等级(floating-point conversion subrank)来排序。次等级在等级相等的类型之间构成一个全序关系。 类型 |
(C++23 起) |
[编辑] 用法
浮点转换等级和次等级也用于
|
(C++23 起) |
- 确定 std::complex 的转换构造函数是否为 explicit,或
- 当将不同浮点类型的参数传递给通用或特殊数学函数时,确定公共浮点类型。
[编辑] 缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
CWG 1642 | C++98 | 常规算术转换可能涉及左值 | 首先应用左值到右值转换 |
CWG 2528 | C++20 | unsigned char 和 unsigned int 之间的三路比较非良构,因为 存在中间的整数提升[1] |
基于提升后的类型确定 公共类型,而不需要 实际提升操作数[2] |
CWG 2892 | C++98 | 当两个操作数都是相同的 浮点类型时,“不需要 进一步转换”的含义不明确 |
更改为“不会执行 进一步转换” |