Общая библиотека C ++ с шаблонами: ошибка неопределенных символов - PullRequest
40 голосов
/ 21 июня 2009

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

Ответы [ 4 ]

40 голосов
/ 21 июня 2009

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

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

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

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

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

19 голосов
/ 21 июня 2009

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

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

6 голосов
/ 21 июня 2009

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

2 голосов
/ 21 июня 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...