C++模板,未定义的引用

Dan*_*oof 28 c++ templates g++ undefined-reference

我有一个声明如下的函数:

template <typename T> 
T read();
Run Code Online (Sandbox Code Playgroud)

并定义如下:

template <typename T>
T packetreader::read() {
    offset += sizeof(T);
    return *(T*)(buf+offset-sizeof(T)); 
}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试在main()函数中使用它时:

packetreader reader;
reader.read<int>();
Run Code Online (Sandbox Code Playgroud)

我从g ++得到以下错误:

g++ -o main main.o packet.o
main.o: In function `main':
main.cpp:(.text+0xcc): undefined reference to `int packetreader::read<int>()'
collect2: ld returned 1 exit status
make: *** [main] Error 1
Run Code Online (Sandbox Code Playgroud)

有人能指出我正确的方向吗?

str*_*ger 24

您需要使用export关键字.但是,我不认为G ++有适当的支持,因此您需要在标题中包含模板函数的定义,以便翻译单元可以使用它.这是因为<int>尚未创建模板的"版本",只有<typename T>"版本".

一个简单的方法是#include.cpp文件.但是,这可能会导致问题,例如,当其他函数位于.cpp文件中时.它也可能会增加编译时间.

一种干净的方法是将模板函数移动到自己的.cpp文件中,并将其包含在标题中使用export关键字并单独编译.

有关为什么要尝试将模板函数定义放在其头文件中(并export完全忽略)的更多信息.


jal*_*alf 12

问题是函数模板不是函数.它是根据需要创建函数的模板.

因此,为了使模板起作用,编译器直观地需要两条信息:模板本身以及应该替换它的类型.这与函数调用不同,只要知道函数存在,编译器就可以生成函数调用.它不需要知道函数的作用,只是它看起来像void Frobnicate(int, float),或者它的签名是什么.

当你声明函数模板而不定义它时,你只是告诉编译器这样的模板是存在的,而不是它的样子.这还不足以让编译器能够实例化它,它也必须能够看到完整的定义.通常的解决方案是将整个模板放在可以包含在需要的标题中.


vav*_*ava 5

模板函数的最佳实践是在头文件中定义它们。它们是在编译时创建的,因此编译器必须有定义才能这样做。

exportfor 模板将得到更多支持时,情况并非如此,但现在它仍然几乎无法使用。