A wrapper/proxy for a class which has a templated interface will always require that the definition of the template class be visible in a header file to the code that calls the wrapper. This is because the code generated for the templated interface depends on the types of the arguments it is called with.
If you're stuck with the existing templated implementation FooImpl
, then as @mars writes in the comments, your only option is:
template <class Implementation>
class FooProxy
{
Implementation * m_ptrImpl;
//...
};
If you can change the existing implementation, the ideal solution would be to refactor the templated methods and split them into two layers; one layer that depends on the argument types, and a second layer that does not. The code in the existing methods that depends on the argument types should be identical in all implementations, so this layer can be moved into a method of the abstract interface class. The remaining code that does not depends on the argument types can be left in a non-templated method of the implementation class, meaning the implementation details can be hidden in the .cpp file.
Here's an example, based on the scenario of a log that supports writing arbitrary types:
LogInterface.h
class LogInterface {
public:
template<typename T>
void write(const T& arg)
{
// converts from 'T' to array of characters.
// calls non-template 'write' as many times as necessary.
}
virtual void write(const char* p, std::size_t n)=0;
};
LogImpl.h
#include "LogInterface.h"
/** Implementation of the original Log class **/
class LogImpl : public LogInterface {
public:
void write(const char* p, std::size_t n);
};
LogProxy.h
#include "LogInterface.h"
class LogProxy : public LogInterface{
protected:
LogInterface* m_ptrImpl; // initialized somewhere with a LogImpl*
public:
void write(const char* p, std::size_t n)
{ m_ptrImpl->write(p, n); }
};