Подтвердить что ты не робот

Общая библиотека С++ с шаблонами: Undefined ошибка символов

Я пытаюсь связать с разделяемой библиотекой с классом шаблона, но он дает мне "undefined символы". Я сократил проблему до 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;
}

Вот как я компилирую библиотеку:

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

И основная программа:

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

Только для получения следующих ошибок:

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

Если я удалю содержимое шаблона в shared.h/cpp и заменим его на "int", все будет хорошо. Кроме того, если я просто скопирую и вставлю код класса шаблона прямо в main.cpp и не свяжусь с разделяемой библиотекой, все будет работать.

Как я могу заставить класс шаблона, подобный этому, работать через общую библиотеку?

Я использую MacOS 10.5 с GCC 4.0.1.

4b9b3361

Ответ 1

В дополнение к другим ответам вы можете явно создавать шаблонные классы. Это полезно, только если вы заранее знаете, какие типы параметров шаблона могут принять. Вы создаете экземпляр шаблона со всеми этими типами в библиотеке.

Для вашего примера для компиляции просто добавьте следующее в конец shared.cpp:

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

Это создает шаблон с типом = int и помещает экземплярный код в общую библиотеку. Добавьте столько явных экземпляров, сколько вам нужно, для всех типов, которые вам нужны.

Опять же, если вы хотите создать экземпляр шаблона с любым произвольным параметром Type, то вы должны добавить определения в заголовочный файл, чтобы компилятор знал исходный код шаблона при создании экземпляра в других единицах компиляции.

Ответ 2

Определения функций шаблона должны находиться в файлах заголовков. Переместите определения из shared.cpp в shared.h.

Таким образом, вы не можете скомпилировать это в общую библиотеку и затем ссылаться на нее. Это просто не работает.

Ответ 3

Вам также нужно включить реализацию классов шаблонов в файлы заголовков. Это ограничение шаблонов в С++. Поэтому либо включите shared.cpp из main (#include), либо просто переместите код из shared.cpp в shared.h

Ответ 4

Компилятор должен видеть весь код для шаблона, поэтому он может генерировать соответствующий код для фактического типа, который вы хотите использовать. Поэтому вы должны поместить весь код в свой .h. файл.