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

nol*_*olk 42 c++ linker gcc templates class

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

shared.h

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

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; }
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

这是我编译库的方式:

g++ -fPIC -c shared.cpp -o shared.o
g++ -dynamiclib -Wl,-dylib_install_name -Wl,libshared.dylib -o libshared.dylib shared.o
Run Code Online (Sandbox Code Playgroud)

主程序:

g++ -c main.cpp
g++ -o main  main.o -L. -lshared
Run Code Online (Sandbox Code Playgroud)

只是为了得到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

如果我删除'模板'的东西shared.h/cpp,并用'int'替换它们,一切正常.此外,如果我只是将模板类代码复制并粘贴到其中main.cpp,并且不链接到共享库,那么一切都可以正常工作.

如何通过共享库获取这样的模板类?

我正在使用带有GCC 4.0.1的MacOS 10.5.

Jul*_*ano 41

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

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

// Instantiate myclass for the supported template type parameters
template class myclass<int>;
template class myclass<long>;
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这正是我所寻找的.非常感谢!有关具有相同问题的其他人的参考:在shared.cpp文件的END处添加模板实例化行. (3认同)

rlb*_*ond 20

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

因此,您无法将其编译为共享库,然后链接到它.它只是不起作用.

  • 那么拥有模板的共享库是不可能的? (2认同)
  • 相反,这太荒谬了.只需将其放在头文件中,然后分享即可.您甚至不需要编译器;)模板在实例化之前不会被编译,因此如果您将模板放在.cpp文件中并将其编译为共享库,则只需删除模板代码.模板定义必须对用户可见. (2认同)
  • 规则的例外:只要“.cpp”文件实例化模板,就可以在“.cpp”文件中定义模板函数。 (2认同)

Căt*_*tiș 6

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