【问题标题】:C++ templates, undefined referenceC++ 模板,未定义的引用
【发布时间】:2010-10-13 12:43:18
【问题描述】:

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

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++ templates g++ undefined-reference


【解决方案1】:

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

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

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

More information on why you should try and put template function definitions in its header file (and ignore export altogether).

【讨论】:

  • 将我的 packet.cpp 代码移动到 packet.h 并将其重命名为我经常在 boost 中使用的“packet.hpp”之类的名称对我来说是个好主意吗?跨度>
  • @Daniel,仅当您的所有函数都是模板函数时。否则,您可以将一些函数移到上面并保留 .cpp 文件。
【解决方案2】:

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

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

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

【讨论】:

    【解决方案3】:

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

    export 的模板将得到更多支持时,情况不会是这样,但现在它仍然几乎不能使用。

    【讨论】:

    【解决方案4】:

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

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

    【讨论】:

    • 科莫我相信。现代版的 MSVC可能,但我自己没有检查过。
    • 最新的VS2008还不支持export关键字。似乎 MS 家伙保留了这个关键字以供将来支持:警告 C4237: 'export' 关键字尚不受支持,但保留以供将来使用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-21
    • 2021-10-22
    • 2014-04-30
    • 2013-02-01
    相关资源
    最近更新 更多