编译以下示例时,我遇到了一个奇怪的问题。
template<typename T>
struct identity {
typedef T type;
};
template<typename T>
void foo(typename identity<T>::type v) {}
template<typename T>
void foo(typename identity<T>::type* v) {}
int main() {
foo<int>(0);
foo<short>(0);
return 0;
}
调用foo<int>(0)
编译,但是,当我调用foo<short>(0)
时,编译器无法推断出0是值还是指针。我使用identity强制显式指定模板参数。编译器(msvc)错误消息:
error C2668: 'foo': ambiguous call to overloaded function
是编译器错误吗?
答案 0 :(得分:3)
不编译器错误。这是因为将0转换为指针类型具有“转换等级”。
C ++11§4.10(转换排名)
空指针常量是一个整数文字(2.13.2),其值为零 或者类型为std :: nullptr_t的prvalue。空指针常量可以是 转换为指针类型;结果是空指针值 该类型并且可以与对象的每个其他值区分开来 指针或函数指针类型。这种转换称为null 指针转换。
因此,当您编写0字面值并且需要转换时,编译器会遇到两个类似等级的重载 - 一个是非指针类型,另一个是指针类型。
更多例子:
foo<short>((short)0); // No conversion necessary: allowed
foo<nullptr_t>(nullptr); // No conversion necessary: allowed
foo<nullptr_t>(0); // ambiguous
foo<nullptr_t>(NULL); // ambigious - another reason to stop using NULL