为何此C++模板示例中T被推导为const int*而非int*?
模板参数推导结果不符预期的原因分析
示例代码
template <class T> void f(const T&&) { std::cout << __PRETTY_FUNCTION__; }; int main(void){ const int *cptr = nullptr; f(std::move(cptr)); }
相关标准条款
根据[temp.deduct.call]/1条款:
模板参数推导通过对比每个参与推导的函数模板参数类型(记为
P)与调用对应实参的类型(记为A)来完成……
根据[temp.deduct.call]/3条款:
若
P是带cv限定的类型,推导时忽略P类型的顶层cv限定符;若P是引用类型,则使用P所引用的类型进行推导。
推导过程与疑问
你预期模板参数T应为int*,推导步骤如下:
P = const T&&, A = const int*; // 将'const T&&'替换为'const T' P = const T, A = const int* T = int*
但GCC和Clang编译结果显示推导得到的T是const int*,疑问是:为何推导得到的模板实参是const int*,而非预期的int*?
原因解析
你出错的核心是对「顶层cv限定符」的概念理解有误,正确的推导步骤应该是:
- 处理引用类型:函数模板参数是
const T&&(右值引用),根据条款,我们取它引用的类型——const T——作为推导用的P。 - 忽略顶层cv限定:
const T中的const是加在T本身上的顶层限定,推导时需要忽略这个顶层const,因此真正参与匹配的P核心类型是T。 - 匹配实参类型:实参
std::move(cptr)的类型A是const int*,这里的const是指针指向对象的限定(底层cv),不属于顶层,不会被忽略。要让T和A匹配,T只能是const int*。
你之前的错误在于,错误地将const T中的const与A中的const对应抵消,认为T=int*。但实际上const T的const是顶层限定,推导时会被直接忽略,根本不会参与和A的匹配。如果强行推导T=int*,const T会变成int* const(指向int的const指针),这和A的const int*(指向const int的指针)是完全不同的类型,编译器无法完成匹配。
内容的提问来源于stack exchange,提问作者mada
相关产品推荐
相关产品推荐

