调用实例化函数时发生链接器错误

Linker error during calling instantiated function

本文关键字:链接 错误 实例化 函数 调用      更新时间:2023-10-16

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

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

演示

为什么第一个例子没有引起成员的隐性讨好,而第二个却引起了。

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

可行函数CCD_ 5被定义为比另一个更好的函数可行函数F2如果对于所有参数iICSi(F1)不是比ICSi(F2)更差的转换序列,然后是

  • [省略了几个不适用的项目符号]
  • F1不是函数模板专业化,F2是函数模板专业
  • [省略了不适用项目符号]

因此,A<int>.foo(3);明确地解析为非模板foo(),您没有为其提供定义,从而导致链接器错误。

我认为在第一种情况下,编译器不知道您想要哪个foo函数。foo(3)可以与CCD_ 14和CCD_。为了纠正这一点,主要只是明确地告诉你想要的模板版本:

 a.foo<int>(3); // or just  a.foo<>(3);

在第二种情况下,您只有一个foo函数。所以没有问题。