Environment: Visual Studio 9, C++ without managed extensions.
I've got a third-party library which exports a fully-specialized template class MyClass<42>
defined in MyClass.h. It gets compiled into a helper loader .lib and a .dll file. The .lib file contains compiled code for this specialization, and necessary symbols. The MyClass.h looks like this:
template<UInt D>
class MyClass {
public:
MyClass() {...};
virtual ~MyClass() {};
}
Now I'd like to use this library. If I include the MyClass.h in a Client.cpp and then compile it, I'll get second copy of these symbols in the Client.obj file. I can get rid of these symbols by defining all the member of that specialization as "extern". My Client.cpp looks like this:
#include <ThirdParty/MyClass.h>
extern template class MyClass<42>;
extern template MyClass<42>::MyClass<42>();
extern template MyClass<42>::~MyClass<42>();
void MyFunction(MyClass<42>& obj) {...}
The problem is that I cannot get rid of the virtual destructor this way. For the virtual destructor I get an almost standard LNK2005 error:
ThirdPartyd.lib(ThirdPartyd.dll) : error LNK2005:
"public: virtual __thiscall MyClass<42>::~MyClass<42>(void)"
(??1?$MyClass@$01@@@UAE@XZ) already defined in Client.obj
What should I do?
The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.
It is possible in C++ to get a special behavior for a particular data type. This is called template specialization. Template allows us to define generic classes and generic functions and thus provide support for generic programming.
An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.
It seems that for virtual methods it is necessary to define them as both extern
and __declspec(dllimport)
at the same time:
extern template __declspec(dllimport) MyClass<42>::~MyClass<42>();
This made my linker happy enough to link my code properly.
I would be very glad if some expert described why is so, or at least pointed to some article explaining this case.
I believe Visual studio uses template specialization in dlls for some stl constructs. string
comes to mind,
I had a quick look at the header file, and it looks like it's using
__declspec(dllimport)
on the declaration of a bunch of specializations. It does not seem that it does so for the whole class though.
From this discussion it sounds like it is possible to declare the whole class as exported, but does not say how.
Sorry for the not-so-complete answer, but hopefully, this can help you explore other venues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With