在一个.hpp头文件里声明了一个类Tensor2,Tensor2类的一个成员函数load()带有模板,然后在.cpp源码文件里写了类的实现,当然包括带模板的函数load()的实现,编译代码时编译过了,但是在链接时始终报找不到这个load函数的定义,错误如下:
/usr/bin/ld: libstreampetr_core.so: undefined reference to `void nv::Tensor2::load<float, float>(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
collect2: error: ld returned 1 exit status
实验比较了一下,调用Tensor2的不带模板的成员函数的代码在链接时没这个问题(平时都是这么写,非常的正常的用法,肯定没问题啦),那带模板的成员函数就为何不行呢?隐约记起N年已前好像遇到过这种问题,把定义也放到头文件里去后链接时就正常了,于是修改了一下,把带模板的函数的定义部分的代码也搬到头文件里去,果然就没问题了。不过还是记不起来这么改了就好了的原因,到网上搜了一下,发现这两篇文章做了解释:
但是两篇文章里面的解释原因上都有点前言不搭后语逻辑含混不清,目前没时间去找C++大砖头书翻看准确的解释,但我觉得原因应该是:
对于普通函数,在源码文件(以.cpp为例)里的定义在编译阶段是会被编译器编译成完整的目标代码;
对于带模板的函数,编译阶段编译器为调用此函数的代码只查找调用代码所在的.cpp文件以及声明此函数的文件里有无此模板函数的定义,能找到的话就根据调用代码处给模板参数传入的值展开模板函数的定义代码并编译出目标代码;对于带模板的函数的声明和定义代码不在一个文件里且调用此函数的代码也与函数的定义不在同一个文件里的情况,编译器除了查找调用此函数的代码所在的文件和声明此函数的代码所在的文件里查找外,并不会去其他文件里查找此函数的定义,因而无法根据模板参数展开此带模板函数的定义代码并编译出对应版本的目标代码,到了链接阶段,链接器为调用此函数的代码查找此函数的定义代码编译出来的目标代码时自然找不到而报错。
记录一下以免将来又忘了再掉同样的坑里
503

被折叠的 条评论
为什么被折叠?



