I have had a similar issue - we've a base class in our system called NamedComponent
and I wanted to create a template which takes an existing named component and converts it into a pimpl facade.
What I did was separate the template into a header and an inline file, and create a function to cause the template to be instantiated. This allows the implementation to be in a library, with the template instantiations of the facade with that implementation, and for the client to be able to use the facade based on the template and a forward declaration of the implementation.
header 'Foo.h':
template<class T> class Foo
{
public:
Foo ();
virtual ~Foo();
private:
T *impl_;
public:
// forwarding functions
void DoIt();
};
inline functions 'Foo.inl':
#include "Foo.h"
template<class T> Foo<T>::Foo() :
impl_ ( new T )
{
}
template<class T> Foo<T>::~Foo()
{
delete impl_;
}
// forwarding functions
template<class T> void Foo<T>::DoIt()
{
impl_ -> DoIt();
}
// force instantiation
template<typename T>
void InstantiateFoo()
{
Foo<T> foo;
foo.DoIt();
}
implementation cpp file - include the template inline functions, define the implementation, reference the instantiation function:
#include "Foo.inl"
class ParticularImpl {
public:
void DoIt() {
std::cout << __FUNCTION__ << std::endl;
}
};
void InstantiateParticularFoo() {
InstantiateFoo<ParticularImpl>();
}
client cpp file - include the template header, forward declare the implementation and use the pimpl facade:
#include "Foo.h"
class ParticularImpl;
int main () {
Foo<ParticularImpl> bar;
bar.DoIt();
}
You may have to fiddle with the InstantiateFoo function's contents to force the compiler to instantiate all functions - in my case, the base called all the pimpl's functions in template methods so once one was referenced, they all were. You don't need to call the Instantiate functions, just link to them.