以下代码产生链接器错误:
#include <iostream>
template<class T>
class A
{
public:
void foo(int);
template<class V> void foo(V v){ std::cout << "foo" << std::endl; }
};
A<int> a;
int main(){ a.foo(3); } //Here is the error.
但是下面的代码工作正常:
#include <iostream>
template<class T>
class A
{
public:
template<class V> void foo(V v){ std::cout << "foo" << std::endl; }
};
A<int> a;
int main(){ a.foo(3); } //OK, call to foo<int>
为什么第一个例子没有引起成员的隐式实例化,但第二个例子确实引起了隐式实例化。
答案 0 :(得分:2)
在所有其他条件相同的情况下,非模板函数优先于重载分辨率中的函数模板。在您的第一个示例中,在A<int>.foo(3);
中,候选人是非模板void foo(int)
,模板template<class V> void foo(V)
包含V = int
。替换后,签名是相同的,因此[over.match.best] /p1.6中的决胜局适用:
可行函数
F1
被定义为比另一个更好的函数 可行函数F2
如果对于所有参数i
,ICSi(F1)
不是a 转换序列比ICSi(F2)
更差,然后
- [省略了几个不适用的子弹]
F1
不是功能模板专精,F2
是功能模板专业化- [不适用的子弹省略]
因此,A<int>.foo(3);
明确地解析为非模板foo()
,您没有提供定义,因此链接器错误。
答案 1 :(得分:1)
我认为在第一种情况下,编译器不知道你想要哪个foo函数。 foo(3)可以匹配void foo(int);
和template<class V> void foo(V v)
。要纠正这个问题,请在main中明确告诉您需要模板版本:
a.foo<int>(3); // or just a.foo<>(3);
在第二种情况下,您只有一个foo函数。所以没有问题。