隐式转换和运算符重载
Implicit conversion and operator overload
所以,我写了这样的东西
#include <iostream>
using namespace std;
void f(int32_t i)
{
cout << "int32: " << i << endl;
}
void f(int16_t i)
{
cout << "int16: " << i << endl;
}
void f(int8_t i)
{
cout << "int8: " << i << endl;
}
void f(uint32_t i)
{
cout << "uint32: " << i << endl;
}
void f(uint16_t i)
{
cout << "uint16: " << i << endl;
}
int main() {
uint8_t i = 0u;
f(i);
return 0;
}
它打印了
int32: 0
我有点懵:
这是定义明确的行为,还是具体实现?
决定这里使用哪种重载以及变量转换成什么类型的规则是什么?
在比较不同重载函数所需的转换时,"promotion" 被认为是比标准 "conversion" 更好的转换序列。每种算术类型最多可以提升为一种其他类型。 (在将参数传递给 printf
等 C 风格的可变参数函数时也会使用提升。一元运算符 +
可用于强制提升算术表达式,如 +n
。 )
对于不是字符类型或 bool
的整数类型,提升的类型是:
- 如果
int
可以表示原类型的所有值,那么int
;
- 否则,如果
unsigned int
可以表示原始类型的所有值,则unsigned int
;
- 否则,原始类型本身(推广没有任何作用)
在您的示例中,比较重载函数时,"exact match" 最好,但没有函数完全采用 int8_t
(或 int8_t&
或 const int8_t&
). uint8_t
的提升类型是 int
,因为它需要支持比 0-255 大得多的范围。显然在您的系统上,int32_t
是 int
的别名,因此函数 void f(int32_t);
只需要对参数进行提升。其他函数都是可行的,但需要对参数进行整数转换。所以void f(int32_t);
被认为是最好的重载。
所以这个问题的技术答案是它是特定于实现的,但只是因为 int
和 <cstdint>
类型之间的关系,而不是因为重载解析规则。
行为定义明确,但特定于实现。使用 16 位 int
会有所不同。
标准中的具体规则是:
[over.best.ics] 用于重载解析。
[conv.prom]积分促销。
所以,我写了这样的东西
#include <iostream>
using namespace std;
void f(int32_t i)
{
cout << "int32: " << i << endl;
}
void f(int16_t i)
{
cout << "int16: " << i << endl;
}
void f(int8_t i)
{
cout << "int8: " << i << endl;
}
void f(uint32_t i)
{
cout << "uint32: " << i << endl;
}
void f(uint16_t i)
{
cout << "uint16: " << i << endl;
}
int main() {
uint8_t i = 0u;
f(i);
return 0;
}
它打印了
int32: 0
我有点懵:
这是定义明确的行为,还是具体实现?
决定这里使用哪种重载以及变量转换成什么类型的规则是什么?
在比较不同重载函数所需的转换时,"promotion" 被认为是比标准 "conversion" 更好的转换序列。每种算术类型最多可以提升为一种其他类型。 (在将参数传递给 printf
等 C 风格的可变参数函数时也会使用提升。一元运算符 +
可用于强制提升算术表达式,如 +n
。 )
对于不是字符类型或 bool
的整数类型,提升的类型是:
- 如果
int
可以表示原类型的所有值,那么int
; - 否则,如果
unsigned int
可以表示原始类型的所有值,则unsigned int
; - 否则,原始类型本身(推广没有任何作用)
在您的示例中,比较重载函数时,"exact match" 最好,但没有函数完全采用 int8_t
(或 int8_t&
或 const int8_t&
). uint8_t
的提升类型是 int
,因为它需要支持比 0-255 大得多的范围。显然在您的系统上,int32_t
是 int
的别名,因此函数 void f(int32_t);
只需要对参数进行提升。其他函数都是可行的,但需要对参数进行整数转换。所以void f(int32_t);
被认为是最好的重载。
所以这个问题的技术答案是它是特定于实现的,但只是因为 int
和 <cstdint>
类型之间的关系,而不是因为重载解析规则。
行为定义明确,但特定于实现。使用 16 位 int
会有所不同。
标准中的具体规则是:
[over.best.ics] 用于重载解析。 [conv.prom]积分促销。