带有模板的 C++ 共享库:未定义符号错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1022623/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:26:24  来源:igfitidea点击:

C++ Shared Library with Templates: Undefined symbols error

c++templatesgccclasslinker

提问by nolk

I'm trying to link to a shared library with a template class, but it is giving me "undefined symbols" errors. I've condensed the problem to about 20 lines of code.

我正在尝试使用模板类链接到共享库,但它给了我“未定义符号”错误。我已将问题浓缩为大约 20 行代码。

shared.h

共享文件

template <class Type> class myclass {
  Type x;
public:
  myclass() { x=0; }
  void setx(Type y);
  Type  getx();
};

shared.cpp

共享文件

#include "shared.h"
template <class Type> void myclass<Type>::setx(Type y) { x = y; }
template <class Type> Type myclass<Type>::getx() { return x; }

main.cpp

主程序

#include <iostream>
#include "shared.h"
using namespace std;

int main(int argc, char *argv[]) {
   myclass<int> m;
   cout << m.getx() << endl;
   m.setx(10);
   cout << m.getx() << endl;
   return 0;
}

This is how I compile the library:

这是我编译库的方式:

g++ -fPIC -c shared.cpp -o shared.o
g++ -dynamiclib -Wl,-dylib_install_name -Wl,libshared.dylib -o libshared.dylib shared.o

And the main program:

和主程序:

g++ -c main.cpp
g++ -o main  main.o -L. -lshared

Only to get the following errors:

只得到以下错误:

Undefined symbols:
"myclass<int>::getx()", referenced from:
  _main in main.o
  _main in main.o
"myclass<int>::setx(int)", referenced from:
  _main in main.o

If I remove the 'template' stuff in shared.h/cpp, and replace them with just 'int', everything works fine. Also, if I just copy&paste the template class code right into main.cpp, and don't link to the shared library, everything works as well.

如果我删除shared.h/cpp. 此外,如果我只是将模板类代码复制并粘贴到 中main.cpp,并且不链接到共享库,则一切正常。

How can I get a template class like this to work through a shared library?

如何让这样的模板类通过共享库工作?

I'm using MacOS 10.5 with GCC 4.0.1.

我使用的是 MacOS 10.5 和 GCC 4.0.1。

采纳答案by Juliano

In addition to the other answers, you can explicitly instantiate template classes. This is only useful if you know beforehand what types the template parameters may assume. You instantiate the template with all these types in the library.

除了其他答案之外,您还可以显式实例化模板类。这仅在您事先知道模板参数可能采用的类型时才有用。您可以使用库中的所有这些类型实例化模板。

For your example to compile, just add the following to the end of shared.cpp:

为了编译您的示例,只需将以下内容添加到shared.cpp 的末尾

// Instantiate myclass for the supported template type parameters
template class myclass<int>;
template class myclass<long>;

This instantiates the template with Type=int and places the instantiated code in the shared library. Add as many explicit instantiations as you need, for all the types you need.

这将使用 Type=int 实例化模板并将实例化的代码放在共享库中。根据需要为所有需要的类型添加尽可能多的显式实例。

Again, if you want to be able to instantiate the template with any arbitrary Type parameter, then you mustadd the definitions to the header file, so that the compiler knows the source code of the template when instantiating it in other compilation units.

同样,如果您希望能够使用任意 Type 参数实例化模板,则必须将定义添加到头文件中,以便编译器在其他编译单元中实例化模板时知道模板的源代码。

回答by rlbond

Template function definitions must reside in header files. Move the definitions from shared.cpp to shared.h.

模板函数定义必须驻留在头文件中。将定义从 shared.cpp 移动到 shared.h。

So, you can't compile this to a shared library and then link to it. It just doesn't work like that.

因此,您无法将其编译为共享库,然后链接到它。它只是不那样工作。

回答by C?t?lin Piti?

You need to include the implementation of the template classes in the header files as well. This is a constraint of templates in C++. So either include shared.cpp from main (#include ) or just move the code from shared.cpp in shared.h

您还需要在头文件中包含模板类的实现。这是 C++ 中模板的约束。因此,要么从 main (#include ) 中包含 shared.cpp 要么只是将 shared.cpp 中的代码移动到 shared.h

回答by nos

The compiler has to see all the code for a template, so it can generate the appropriate code for the actual type you want to use. So you should place all the code in your .h. file.

编译器必须查看模板的所有代码,因此它可以为您要使用的实际类型生成适当的代码。所以你应该把所有的代码放在你的 .h 中。文件。