Вопрос по gcc, linker, c++ – Общая библиотека C ++ с шаблонами: ошибка неопределенных символов

39

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

Дубликат:stackoverflow.com/questions/999358/… Todd Gardner

Ваш Ответ

4   ответа
2

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

6

ные файлы. Это ограничение шаблонов в C ++. Так что или включите shared.cpp из main (#include) или просто переместите код из shared.cpp в shared.h

18

Переместите определения из shared.cpp в shared.h.

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

Наоборот, это смехотворно легко. Просто поместите это в заголовочный файл и поделитесь этим. Тогда вам даже не понадобится компилятор;) Шаблоны не будут скомпилированы, пока они не будут созданы, поэтому, если вы поместите шаблон в файл .cpp и скомпилируете его как общую библиотеку, код шаблона просто удаляется. Определение шаблона должно быть видимым для пользователя.
Вы абсолютно уверены? Потому что я в настоящее время работаю с общей библиотекой, которая создает шаблоны во время ее компиляции. Код невидим для пользователя, но его можно использовать. Проблемы компиляции могут возникнуть при смешивании специализаций, которые требуют генерации, и других, которые уже созданы. Но кроме этого все работает нормально. Протестировано с g ++ и msvc.
Исключение из правила: оноis можно определить функцию шаблона в.cpp файл & # x2014; покаonly тот.cpp файл создает экземпляр шаблона.
То есть невозможно иметь общую библиотеку с шаблонами? nolk
40

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

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

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

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

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

Это именно то, что я искал. Спасибо вам большое! Для ссылки на других людей с такой же проблемой: Добавьте строки создания шаблона в КОНЕЦ файла shared.cpp. nolk
@ForceBru: в любом из них. Я предлагаю исходный файл, который соответствует заголовочному файлу, который определяет шаблон.
Это здорово, но что если у меня естьtwo source filesа не тот, который делает ОП? Где я должен добавить эти строки тогда?

Похожие вопросы