Экспорт символа C ++ для класса, расширяющего шаблон класса - PullRequest
2 голосов
/ 17 июня 2011

Я работаю над проектом C ++, созданным с помощью Visual Studio 2008. Я определяю (в проекте, создающем dll) класс шаблона и производный, не шаблонный, один:

template <class T>
struct DLL_EXPORT Base {
  int base() { return 1; }
};

struct DLL_EXPORT Deriv: public Base<Deriv> {
  int deriv() { return 1; }
};

DLL_EXPORT это обычный материал:

#ifdef COMPILING_MY_DLL
    #define DLL_EXPORT __declspec(dllexport)
#else
    #define DLL_EXPORT __declspec(dllimport)
#endif

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

Deriv d;
d.deriv();

Но если я пытаюсь вызвать d.base(), я получаю следующую ошибку компоновщика:

error LNK2019: unresolved external symbol "__declspec(dllimport) public: int __thiscall Base<struct Deriv>::base(void)" (__imp_?base@?$Base@UDeriv@@@@QAEHXZ)

Если в другом месте моего dll-кода я использую функцию d.base (), она работает хорошо, и ошибка компоновщика исчезает в проекте пользователя. И если я удалю часть шаблона (это не очень полезно в моем примере, но в реальной ситуации это так), все в порядке.

Похоже, что функция не компилируется, если она не используется, или что-то эквивалентное. Есть идеи?

Заранее спасибо.

Ответы [ 3 ]

3 голосов
/ 17 июня 2011

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

3 голосов
/ 17 июня 2011

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

В одном из файлов .cc в вашей DLL (не в заголовочном файле),включите определение вашего шаблона и напишите:

template int Base<Deriv>::base();

Это должно заставить компилятор поместить код для Base<Deriv>::base() в этот модуль компиляции, чтобы ваш компоновщик мог его найти.

2 голосов
/ 17 июня 2011

Я не знаю много об этом, но я думаю, что вы могли бы это исправить, написав

template struct Base<Derive>;

где-нибудь в вашем исходном файле.(или возможно template DLL_EXPORT struct Base<Derive>;)

...