Использование шаблонных классов и функций в общем объекте / DLL - PullRequest
6 голосов
/ 21 января 2010

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

Вот урезанный пример того, как я делаю экспорт библиотеки:

#if defined(_MSC_VER) && defined(_DLL)
    //    Microsoft 
    #define EXPORT __declspec(dllexport)
    #define IMPORT __declspec(dllimport)
#elif defined(_GCC)
    //    GCC
    #define EXPORT __attribute__((visibility("default")))
    #define IMPORT
#else
    //    do nothing and hope for the best at link time
    #define EXPORT
    #define IMPORT
#endif

#ifdef _CORE_COMPILATION
#define PUBLIC_CORE EXPORT
#define EXTERNAL_CORE
#else
#define PUBLIC_CORE IMPORT
#define EXTERNAL_CORE extern
#endif

#include <deque>

//    force exporting of templates
EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>;
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >;

class PUBLIC_CORE MyObject
{
private:
    std::deque<int> m_deque;
};

SO , моя проблема в том, что при компиляции в Visual Studio (как 2008, так и 2010) я получаю следующее предупреждение:

предупреждение C4251: 'Станд :: _ Deque_val <_Ty, _Alloc> :: _ ALMap' : класс 'std :: allocator <_Ty>' должен иметь dll-интерфейс для использования клиенты класса 'Станд :: _ Deque_val <_Ty, _Alloc>'

Что означает, что я не экспортировал std::allocator<int>, который у меня есть. И это не похоже на мой экспорт неправильно, так как не включая

EXTERNAL_CORE template class PUBLIC_CORE std::allocator<int>;
EXTERNAL_CORE template class PUBLIC_CORE std::deque<int, std::allocator<int> >;

выдает предупреждение:

предупреждение C4251: «MyObject :: m_deque»: класс 'std :: deque <_Ty>' должен иметь dll-интерфейс для использования клиентами класс 'MyObject'

Единственное, о чем я могу думать, это то, что _Ty, о котором идет речь о std::allocator, как-то не int, но я не могу найти никаких признаков того, что это было бы иначе, так как std::deque<int> будет логически выделяться с std::allocator<int>.

Потребляющее приложение может использовать класс просто отлично, но у меня есть ощущение, что это предупреждение не следует игнорировать. При компиляции с g ++ в Linux ошибки не выдаются (хотя это не означает, что все работает правильно). G ++ автоматически делает то, чего не может MSVC? Я нацеливался на GCC в Linux, LLVM в OSX и MSVC в Windows, но потенциально я мог бы перейти на MinGW для разработки Windows, так что отказ от MSVC не исключен (если это окажется слишком большим неудобством) .

1 Ответ

3 голосов
/ 21 января 2010

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

Это означает, что если вы скомпилируете свой заголовочный файл с помощью компилятора A, он может создать совершенно другой deque<int>, чем компилятор B. Порядок некоторых членов может измениться для одного или даже фактического типа некоторых переменных-членов.

И это то, за что вас предупреждает компилятор.

РЕДАКТИРОВАТЬ: добавляет некоторые последствия к объяснению

Таким образом, ваши совместно используемые библиотеки будут хорошо работать вместе только при компиляции одним и тем же компилятором. Если вы хотите, чтобы они работали вместе, вы можете либо убедиться, что весь клиентский код «видит» одно и то же объявление (используя одну и ту же реализацию stl), либо отказаться от добавления шаблонов в свой API.

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