调用实例化函数期间链接器错误

时间:2015-03-03 04:51:31

标签: c++ templates

以下代码产生链接器错误:

#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.

DEMO

但是下面的代码工作正常:

#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>

DEMO

为什么第一个例子没有引起成员的隐式实例化,但第二个例子确实引起了隐式实例化。

2 个答案:

答案 0 :(得分:2)

在所有其他条件相同的情况下,非模板函数优先于重载分辨率中的函数模板。在您的第一个示例中,在A<int>.foo(3);中,候选人是非模板void foo(int),模板template<class V> void foo(V)包含V = int。替换后,签名是相同的,因此[over.match.best] /p1.6中的决胜局适用:

  

可行函数F1被定义为比另一个更好的函数   可行函数F2如果对于所有参数iICSi(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函数。所以没有问题。