It is possible, but a naive implementation is not what you want.
The problem is that templates are generally inlined, the naive implementation would be:
template <class Object>
class Pimpl
{
public:
explicit Pimpl(Object* obj): mObject(obj) {}
~Pimpl() { delete mObject; }
// either deep copy or no copy
private:
Object* mObject;
};
Now the problem is that you don't want Object
to be known in your header file in general (not for binary compatibility, but for dependency management). And if Object
is not known, then you cannot implement the Destructor
, Copy Constructor
and Assignment Operator
directly...
The problem is far from being unsolvable however! Boost indeed has solve it for the shared_ptr
.
The idea is to pass a second item in the constructor, that will take care of releasing the memory of the first, and that will be provided with a nice default implementation.
This works with an indirection, of course.
namespace detail {
template <class Object>
struct Deleter { virtual void do(Object*) = 0; };
}
template <class Object>
class Pimpl
{
public:
typedef detail::Deleter<Object> deleter_type;
typedef boost::shared_ptr<deleter_type> deleter_pointer;
Pimpl(std::auto_ptr<Object> obj, deleter_pointer del);
~Pimpl();
Pimpl(const Pimpl&);
Pimpl& operator(const Pimpl&);
private:
Object* mObject;
deleter_pointer mDeleter;
};
It's a classic idiom in C++, add yet another level of indirection :)