重载决议与模板实参推导:为何整数0表现特殊?
C++模板重载中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)会被实例化为f(int),属于精确匹配,因此调用第一个函数,输出first。f<size_t>(0):显式指定模板参数T=size_t后,两个模板分别实例化为:void f(size_t):实参0(int类型)可通过整数提升转换为size_t,属于可行匹配;void f(size_t*):0是空指针常量,可隐式转换为任意指针类型(此处为size_t*),同样属于可行匹配。
此时两个函数都能匹配实参,但根据C++模板重载决议规则:更特化的模板会被优先选择。
template<typename T> void f(T*)是template<typename T> void f(T)的更特化版本,因此最终调用第二个函数,输出second。f<size_t>(0UL):实参0UL本身就是size_t类型,对于实例化后的f(size_t)属于精确匹配(无需任何转换);而匹配f(size_t*)需要将0UL(空指针常量)转换为指针类型,属于等级更低的转换。精确匹配优先级更高,因此调用第一个函数,输出first。f(1):整数字面量1的类型是int,模板推导T=int,匹配第一个函数,输出first。f<size_t>(1):实参1不是空指针常量,无法转换为size_t*类型,因此只有f(size_t)是可行匹配,调用第一个函数,输出first。
关键知识点补充
- 空指针常量定义:值为0的整数字面量(如
0、0L、0UL)或std::nullptr_t类型的纯右值,可隐式转换为任意指针类型。 - 模板重载决议规则:当多个模板实例化后的函数都能匹配实参时,更特化的模板会被优先选中,优先级高于普通的转换等级比较(仅当特化程度相同时,才会比较转换等级)。
内容的提问来源于stack exchange,提问作者toxic
相关产品推荐
相关产品推荐

