我在用C ++编写的共享库中有一个模板函数(该函数不会在库中的任何地方调用,所以不应该生成它,我错了吗?)[g ++,Linux]
我尝试在应用程序中使用此模板函数但编译器给出了链接错误。我使用objdump搜索了函数但是我无法在.so中看到函数 有没有办法解决这个问题?
答案 0 :(得分:6)
模板函数属于库头,它们不在DLL共享库中编译。因此,将所有模板函数移动到标题中,并在应用程序中包含该标题。
答案 1 :(得分:6)
最简单的方法是将所有模板代码移动到头文件中(如其他答案中所述) 但是这不是唯一的解决方案。
模板不是实际功能。
当存在函数的实例化时,模板成为函数。这可以隐式或明确地完成。无论何时使用该函数,都存在隐式实例。但您也可以明确地实现模板功能。
因此,您应该能够在共享库中链接模板函数的任何实例化版本。
头文件,因此我们遵守一个定义规则。
// tt.h
template<typename T>
int doStuff(Tconst &t);
源文件:
// tt.cpp
#include "tt.h"
template<typename T>
int doStuff(Tconst &t)
{
return 4;
}
void plop()
{
int x = 6;
// implicit instanciation of doStuff<int>(int const&);
doStuff(x);
}
// explicit instanciation of template
template int doStuff<float>(float const&);
如果我将上述内容编译成共享库 然后会有两个可用的doStuff()方法。
g ++ -shared -o tt.so tt.cpp
现在,如果我们有一个seprate文件,我们链接到共享库:
// main.cpp
#include "tt.h"
int main()
{
doStuff(5); // doStuff<int>()
doStuff(6.0f); // doStuff<float>()
}
g ++ main.cpp t.so
即使main看不到任何模板代码,编译也很好。
答案 2 :(得分:1)
模板很难由编译器开发人员实现,因此,大多数C ++编译器实际上都要求您将模板代码放在头文件中,甚至是完整的类实现(尽管有一些例外和技巧可以避免这种情况)。
对于您的情况,您需要做的就是将您的功能模板移动到头文件(可能包含其他功能模板),并在需要时将其导入。
希望有所帮助。
答案 3 :(得分:0)
您要使用的功能需要在您的库或代码中的某处实例化。您的编译器应该在程序代码中为您生成实例化,除非原型被声明为extern。听起来你想要在库中显式实例化该函数。在库中的一个源文件中,您只需添加如下行:
template return_type function_name(param_type,param_type);
并且应该显式生成函数的代码。
答案 4 :(得分:0)
前段时间我发现自己处于相同的状况,所以我对此进行了调查。基本上模板不会产生任何目标代码,它们只是编译器的定义。当您实例化std::list<Foo> l
之类的对象时,编译器将为Foo对象列表生成实例和专用代码。
这导致两个后果:
std::list<Foo>
作为数据类型的两个.cpp文件将生成相同可执行代码的副本。第二点在链接阶段使事情变得困难,因为链接器应该处理双重定义。可能的链接策略是为每个目标代码保留一份副本。更聪明的链接器可能会尝试优化,但这会带来很大的复杂性。
我想这就是为什么gcc编译C ++需要很长时间,而C语言的速度要快得多。