例如,C++不会实例化模板T = Hoge&.
一个最小的例子:
hoge.h:
#include<cstdio>
class Hoge
{
public:
Hoge()
: hoge(0)
{
}
~Hoge()
{
}
int hoge;
void print() { printf("%d\n", hoge); }
};
template<typename T>
void f(T a);
Run Code Online (Sandbox Code Playgroud)hoge.cpp:
#include "hoge.h"
template<typename T>
void f(T a)
{
a.print();
}
template void f<Hoge &>(Hoge &a);
Run Code Online (Sandbox Code Playgroud)main.cpp:
#include "hoge.h"
int main(void)
{
Hoge h;
f(h);
return 0;
}
Run Code Online (Sandbox Code Playgroud)我编译了这些:g++ -std=c++11 main.cpp hoge.cpp.但它给出了链接器错误:
Undefined symbols for architecture x86_64:
"void f<Hoge>(Hoge)", referenced from:
_main in aa-e35088.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
接下来,我改变了f(h)在 main.cpp以f<Hoge &>,错误消失.
为什么f<Hoge &>(Hoge &)不在第一种情况下调用?对于这种情况,我可以通过f<Hoge &>每次键入来避免错误.但是,当涉及到重载运算符时,它无法完成.
请告诉我如何解决这个错误.
joh*_*n d 16
编译器将尝试推导出最简单的模板T.在这里,T=Hoge很好,所以编译器不会尝试更详细的表单.
你可以清楚地表明你的意图.请尝试以下方法:
template<typename T>
void f(T& a);
Run Code Online (Sandbox Code Playgroud)
T仍将推断为Hoge,但您的功能f将获得参考.这使读者可以直接在f原型中清楚地看到它.
当涉及到模板参数推导时,在编译器引擎下会发生很多规则.当我说编译器推导出最简单的T时,我真的是偷工减料.这是一个有效的来源:cppreference
您可以按照您的方式使用引用类型实例化该函数.但是,编译器不会 将模板参数推断为引用类型.您可以通过不让编译器推断出参数而是指定参数来验证您是否可以实例化函数模板OK:
f<Hoge&>(h);
Run Code Online (Sandbox Code Playgroud)
如果您想获得推断的引用类型,则需要使用转发引用作为函数模板的参数:
template <typename T>
void f(T&& a);
Run Code Online (Sandbox Code Playgroud)
使用转发引用作为模板参数并传递Hoge参数时,根据参数的值类别推导出该参数:
Hoge h;
Hoge const c;
f(h); // T becomes Hoge&
f(c); // T becomes Hoge const&
f(Hoge()); // T becomes Hoge
Run Code Online (Sandbox Code Playgroud)