In my DLL, I have a class template and a second class derived from an instantiation of that template. Both classes shall be exported and usable in other DLLs. The compiler is Visual Studio 2013. I want the template code to be instantiated in exactly one translation unit, so I employ explicit instantiation.
The code in DLL1 is distributed as follows. Base class template:
// In BaseTemplate.h:
#pragma once
template<typename T>
class BaseTemplate
{
public:
T foo(T t);
};
// declare explicit instantiation
extern template class BaseTemplate < int >;
// In BaseTemplate.cpp:
#include "BaseTemplate.h"
// template method definition
template<class T>
T BaseTemplate<T>::foo(T t)
{
return t;
}
// explicit instantiation and export
template class __declspec(dllexport) BaseTemplate < int >;
Derived class:
// In Derived.h:
#pragma once
#include "BaseTemplate.h"
#ifdef DLL1_EXPORTS // this is predefined in DLL1
#define DLL1_API __declspec(dllexport)
#else
#define DLL1_API __declspec(dllimport)
#endif
class DLL1_API Derived : public BaseTemplate < int >
{
public:
void bar();
};
The theory was that the extern statement prevents instantiation in all translation units except for BaseTemplate.cpp, where explicit instantiation is performed. However, I get the following warning (which is treated as error in my project and thus breaks the build):
1> basetemplate.h(19): warning C4661: 'int BaseTemplate<int>::foo(T)' :
1> no suitable definition provided for explicit template instantiation request
1> with
1> [
1> T=int
1> ]
1> basetemplate.h(15) : see declaration of 'BaseTemplate<int>::foo'
It seems that the export of the derived class triggers instantiation, ignoring the extern statement. If I remove the export macro from the Derived class, DLL1 compiles without warning (but other DLLs obviously will fail to link). If I aggregate a member of type BaseTemplate in class Derived instead of inheriting, it works as well (even with the export).
How can I combine explicit template instantiation and exported derived classes in Visual Studio?