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

C++ templates, undefined reference

提问人:Daniel Sloof 提问时间:3/16/2009 最后编辑:Daniel Sloof 更新时间:3/30/2014 访问量:32466

问:

我有一个这样的函数声明:

template <typename T> 
T read();

并按如下定义:

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

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

packetreader reader;
reader.read<int>();

我从 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

谁能为我指出正确的方向?

C 模板 G++ 未定义引用

答:

25赞 strager 3/16/2009 #1

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

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

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

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

评论

0赞 Daniel Sloof 3/16/2009
将我的数据包.cpp代码移动到packet.h并将其重命名为我在boost中经常使用的“packet.hpp”之类的东西对我来说是一个好主意吗?
1赞 strager 3/16/2009
@Daniel,仅当所有函数都是模板函数时。否则,您可以移动某些函数并保留 .cpp 文件。
5赞 vava 3/16/2009 #2

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

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

评论

1赞 uckelman 9/29/2010
我不建议使用 .根据 parashift.com/c++-faq-lite/templates.html#faq-35.14 的说法,它已被投票排除在 C++0x 标准之外。export
12赞 jalf 3/16/2009 #3

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

因此,要使模板正常工作,编译器直观地需要两条信息:模板本身和应替换到其中的类型。 这与函数调用不同,编译器可以在知道函数存在后立即生成函数调用。它不需要知道函数的作用,只需要知道它的外观,或者它的签名是什么。void Frobnicate(int, float)

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

0赞 Baiyan Huang 3/16/2009 #4

他们的任何编译器支持模板是否单独编译?

据我所知,通常的做法是在头文件中声明和实现模板函数

评论

0赞 vava 3/16/2009
我相信科莫。现代版本的 MSVC 可能会,但我自己没有检查过。
0赞 Baiyan Huang 3/16/2009
最新的 VS2008 还不支持 export 关键字。似乎 MS 家伙保留了这个关键字以供将来支持:警告 C4237:“导出”关键字尚不受支持,但保留供将来使用