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 ofA::foo
。这实际上是由于在类成员访问表达式中使用了函数模板造成的。但仍然不清楚是否存在重新定义错误。我认为它应该被打印出来。@DmitryFucintv为什么会出现重新定义错误?函数和函数模板是单独的实体;它们重载。但是隐式的函数模板的安装是函数,而不是函数模板。这就是我认为重新定义错误的原因。因此,它违反了3.2/4[basic.def.odr]@DmitryFucintv No.foo
和foo
是不同的实体。
a.foo<int>(3); // or just a.foo<>(3);