Какие приемы могут использоваться для уменьшения рабочей нагрузки реализации pImpl классы?
Заголовок:
class Foo {
struct Impl;
boost::scoped_ptr<Impl> self;
public:
Foo(int arg);
~Foo();
// Public member functions go here
};
Реализация:
struct Foo::Impl {
Impl(int arg): something(arg) {}
// All data members and private functions go here
};
Foo::Foo(int arg): self(new Impl(arg)) {}
Foo::~Foo() {}
// Foo's public functions go here (and they refer to data as self->something)
Как Вы улучшили бы это, с помощью Повышения, возможно наследования, CRTP или других приемов к предотвращению такого количества шаблонного кода, как возможно? Производительность во время выполнения не является проблемой.
Это возможно, но наивная реализация - это не то, что вам нужно.
Проблема в том, что шаблоны обычно встроены, наивная реализация была бы такой:
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
был известен в вашем файле заголовка в целом (не для двоичная совместимость, но для управления зависимостями). И если Объект
неизвестен, то вы не можете напрямую реализовать Деструктор
, Конструктор копирования
и Оператор присваивания
...
Однако проблема далеко не неразрешима! 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 ++, добавьте еще один уровень косвенности :)