Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DLL and fully-specialized template class

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?

like image 404
liori Avatar asked Feb 17 '10 21:02

liori


People also ask

What are specialized templates?

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.

What is template specialization used for?

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.

Are template specializations inline?

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.


2 Answers

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.

like image 111
liori Avatar answered Oct 26 '22 06:10

liori


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.

like image 34
Bahbar Avatar answered Oct 26 '22 06:10

Bahbar