Это возможно, но наивная реализация - это не то, что вам нужно.
Проблема в том, что шаблоны обычно встроены, наивная реализация будет выглядеть так:
template <class Object>
class Pimpl
{
public:
explicit Pimpl(Object* obj): mObject(obj) {}
~Pimpl() { delete mObject; }
// either deep copy or no copy
private:
Object* mObject;
};
Теперь проблемав том, что вы не хотите, чтобы Object
был известен в вашем заголовочном файле в целом (не для двоичной совместимости, а для управления зависимостями).А если Object
неизвестно, то вы не можете напрямую реализовать Destructor
, Copy Constructor
и Assignment Operator
...
Однако проблема далеко не решаема!Boost действительно решил эту проблему для shared_ptr
.
Идея состоит в том, чтобы передать второй элемент в конструктор, который позаботится об освобождении памяти первого, и ему будет предоставлен хороший стандарт по умолчанию.реализация.
Конечно, это работает с косвенным указанием.
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;
};
Это классическая идиома в C ++, добавьте еще один уровень косвенного обращения:)