C ++: функция-член, явная реализация шаблона в DLL

Я создаю DLL в C++ с помощью Visual Studio 2013 на Windows 8.1 Update 1,
Есть класс под названием XMLData которая имеет публичную функцию-член под названием getAttribute,

XMLData.h

namespace DDGL
{
class DLL_EXPORTED XMLData
{

...

// const char* is used to avoid problems with trying to pass an
// std::string over DLL boundaries
template <typename Type> Type getAttribute (const char* attribute) const;

...

};
}

Внутри DLL каждое использование создается, как и следовало ожидать, и работает нормально.

Однако внутри приложения я, конечно, получу неопределенные ссылки для <typename Type>Это не были использованы в DLL.

Итак, я пытаюсь использовать явное создание экземпляра шаблона (я бы предпочел не помещать реализацию в заголовок для обучения в случае чего-либо):

XMLData.cpp

namespace DDGL
{

...

// getAttribute definition

...

template float XMLData::getAttribute(const char* attribute) const;

...

}

Тем не менее, я все еще получаю неразрешенный внешний вид в приложении, использующем DLL:

Выход

error LNK2019: unresolved external symbol "public: float __thiscall DDGL::XMLData::getAttribute<float>(char const *)const " (??$getAttribute@M@XMLData@DDGL@@QBEMPBD@Z) referenced in function "class std::shared_ptr<class DDGL::IGameObject> __cdecl SimpleExplodingRocketDeserialiser(class DDGL::XMLData)" (?SimpleExplodingRocketDeserialiser@@YA?AV?$shared_ptr@VIGameObject@DDGL@@@std@@VXMLData@DDGL@@@Z)

DLL_EXPORTED

#ifdef DDGL_DLL_BUILDING
#define DLL_EXPORTED __declspec(dllexport)
#else
#define DLL_EXPORTED __declspec(dllimport)
#endif

Куда я иду не так?

1

Решение

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

Решением было сделать следующее:

namespace DDGL
{
class DLL_EXPORTED XMLData
{

...

// const char* is used to avoid problems with trying to pass an
// std::string over DLL boundaries
template <typename Type> Type getAttribute (const char* attribute) const;

...

};

DLL_TEMPLATE_CLASS_MEMBER float XMLData::getAttribute(const char* attribute) const;
}

куда DLL_TEMPLATE_CLASS_MEMBER был определен как:

#ifdef DDGL_DLL_BUILDING
#define DLL_TEMPLATE_CLASS_MEMBER template DLL_EXPORTED
#else
#define DLL_TEMPLATE_CLASS_MEMBER extern template DLL_EXPORTED
#endif

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

0

Другие решения

Хотя решение @OMGtechy работает, я думаю, что это излишнее.
Достаточно указать DLL_EXPORTED как для объявления шаблона, так и для определения шаблона.

В заголовочном файле:

namespace DDGL
{
class DLL_EXPORTED XMLData
{
template <typename Type> DLL_EXPORTED Type getAttribute (const char* attribute) const;

};
}

В файле .cpp, определяющем функцию:

namespace DDGL
{
template<> DLL_EXPORTED float XMLData::getAttribute(const char* attribute) const {
// Function body goes here
}
}

Проверено на MSVC ++ 2017.

Несколько мыслей: думаю, было бы логично, если DLL_EXPORTED по определению класса тоже работал над его шаблонными методами. Не шаблонные методы не требуют DLL_EXPORTED снова на каждый метод. Так что же такого особенного в шаблонных методах? Я не знаю точно.

0

По вопросам рекламы [email protected]