Ответ 1
Реализация pimpl из Loki может быть хорошим ответом. См. Также статья DDJ об этом.
Какие трюки можно использовать для минимизации рабочей нагрузки при реализации классов 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 public functions go here (and they refer to data as self->something)
Как бы вы это улучшили, используя Boost, возможно наследование, CRTP или другие трюки, чтобы избежать как можно большего числа шаблонов? Производительность выполнения не является проблемой.
Реализация pimpl из Loki может быть хорошим ответом. См. Также статья DDJ об этом.
Возможно, но наивная реализация - это не то, что вы хотите.
Проблема в том, что шаблоны, как правило, встроены, наивная реализация:
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;
};
Это классическая идиома в С++, добавьте еще один уровень косвенности:)