在下面的示例中,
0
的行为方式很特殊,我想知道为什么。我的理解也如下。
#include <iostream>
template<typename T>
void f(T a) {
std::cout << "first" << std::endl;
}
template<typename T>
void f(T* a) {
std::cout << "second" << std::endl;
}
int main()
{
f(0);
f<size_t>(0);
f<size_t>(0UL);
f(1);
f<size_t>(1);
}
输出:
first
second
first
first
first
我的理解:
f(0)
- 模板参数推导,整数文字 0
是 int
类型,因此第一个 f
与 T=int
选择
f<size_t>(0)
- 使用整数提升显式模板实例化,选择类型为T=size_t
,选择第一个函数,并且0
从int
到size_t
升级(我错了)
f<size_t>(0UL)
- 与上面相同,但没有促销(0 已经是类型size_t
)
f(1)
- 与 1 相同。
f<size_t>(1)
- 与2相同。(我出于某种原因在这里??)
注意:
我知道
0
可以隐式转换为空指针:
空指针常量是一个值为 0 的整数文字 (5.13.2) 或 std::nullptr_t 类型的纯右值
但是,从标准中我也知道,推广比转化更优先:
每种类型的标准转换序列都分配有以下三种类型之一 排名:
- 精确匹配:无需转换,左值到右值 转换、限定转换、函数指针 conversion,(C++17 起)用户定义的类类型到 同班
- 促销:积分促销、浮点促销
- 转换:积分转换、浮点转换、 浮点积分转换、指针转换、成员指针 转换、布尔转换、派生的用户定义转换 类到其基础
- 具有整数提升的显式模板实例化,选择的类型是 T=size_t,选择第一个函数并将 0 从 int 提升到 size_t(我错了)jf<size_t>(0)
f<size_t>(0)
调用/使用第二个重载f(T*)
的原因是因为部分排序规则。特别是,第二个重载f(T* a)
比第一个重载f(T a)
更专业。