class A { public: typedef int _foo; };
class B {};
template<class T>
typename T::_foo Foo(int)
{
cout << "Foo(int)\n"; return typename T::_foo();
}
template<class T>
typename T Foo(char)
{
cout << "Foo(char)\n"; return typename T();
}
int main()
{
Foo<A>(0); // Writes "Foo(int)", as expected.
Foo<B>(0); // Writes "Foo(char), expected error unable to compile template.
return 0;
}
有两个类A和B。A定义了typedef _foo,而B没有。函数模板Foo有两个重载版本,一个是Foo(int),另一个是Foo(char)。Foo(int)返回T ::_foo,Foo(char)返回T。
然后调用Foo(0)两次。这是Foo(int)的精确匹配,所以我希望Foo<A>(0)能够编译成功,而Foo<B>(0)不能编译成功,因为B未定义在模板中使用的类型_foo。
实际上发生的事情是Foo<B>(0)完全忽略了Foo(int),而是实例化了Foo(char)。但根据常规的重载解析规则,Foo(0)显然是Foo(int)的精确匹配,唯一使Foo(char)更具可行性的是返回类型,而不应该被考虑。
为了验证影响重载分辨率的是返回值,请添加以下内容:
template<class T>
void Bar(int) { typename T::_foo a; cout << "Bar(int)\n"; }
template<class T>
void Bar(char) { cout << "Bar(char)\n"; }
Bar<A>(0); // Writes "Bar(int), as expected.
//Bar<B>(0); // Error C2039: '_foo' : is not a member of 'B', as expected.
这表明在没有返回值的情况下,Foo(int)确实是正确的重载函数,如果模板无法从其模板参数解析所使用的类型,则编译失败是正常的结果。