Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 调用实例化函数时发生链接器错误_C++_Templates - Fatal编程技术网

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

C++ 调用实例化函数时发生链接器错误,c++,templates,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 e

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

#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.
#包括
模板
甲级
{
公众:
void foo(int);

模板void foo(V){std::cout我认为在第一种情况下,编译器不知道您需要哪个foo函数。foo(3)可以同时匹配
void foo(int);
template void foo(V)
。要纠正这一点,主要是明确地告诉您需要模板版本:

 a.foo<int>(3); // or just  a.foo<>(3);
a.foo(3);//或者只是a.foo(3);

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

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

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

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

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

它确实知道您想要哪一个链接器错误,或者它不会是链接器错误。@t.C.原因是什么?可能我的措辞不正确,或者整个答案不正确?但为什么我们不在示例中得到重新定义错误?我们提供了函数和函数的定义板。
A
的隐式实例化导致了
A::foo
的隐式实例化,因此事实上我们有两个名为
foo
的已定义成员函数。我想一定是关于重新定义的错误……对不起,
A
的隐式实例化导致了隐式实例化n of
A::foo
。这实际上是由于在类成员访问表达式中使用了函数模板造成的。但仍然不清楚是否存在重新定义错误。我认为它应该被打印出来。@DmitryFucintv为什么会出现重新定义错误?函数和函数模板是单独的实体;它们重载。但是隐式的函数模板的安装是函数,而不是函数模板。这就是我认为重新定义错误的原因。因此,它违反了3.2/4[basic.def.odr]@DmitryFucintv No.
foo
foo
是不同的实体。
 a.foo<int>(3); // or just  a.foo<>(3);