c++ boost pimpl-idiom

c++ - Implementando pImpl con cantidad mínima de código



boost pimpl-idiom (2)

Es posible, pero una implementación ingenua no es lo que quieres.

El problema es que las plantillas generalmente están en línea, la implementación ingenua sería:

template <class Object> class Pimpl { public: explicit Pimpl(Object* obj): mObject(obj) {} ~Pimpl() { delete mObject; } // either deep copy or no copy private: Object* mObject; };

Ahora el problema es que no quiere que Object se conozca en su archivo de encabezado en general (no para compatibilidad binaria, sino para administración de dependencias). Y si no se conoce el objeto, entonces no se puede implementar Destructor , Copy Constructor y Assignment Operator directamente ...

¡El problema está lejos de ser insoluble sin embargo! Boost de hecho lo ha resuelto para shared_ptr .

La idea es pasar un segundo elemento en el constructor, que se encargará de liberar la memoria del primero, y que se le proporcionará una buena implementación predeterminada.

Esto funciona con una indirección, por supuesto.

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; };

Es un modismo clásico en C ++, agrega otro nivel de indirección :)

¿Qué tipo de trucos se pueden utilizar para minimizar la carga de trabajo de implementar clases de pImpl?

Encabezamiento:

class Foo { struct Impl; boost::scoped_ptr<Impl> self; public: Foo(int arg); ~Foo(); // Public member functions go here };

Implementación:

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)

¿Cómo mejoraría esto, usando Boost, posiblemente herencia, CRTP u otros trucos para evitar tanto código repetitivo como sea posible? El rendimiento del tiempo de ejecución no es un problema.


La implementación de pimpl de Loki puede ser una buena respuesta. Ver también un artículo de DDJ sobre esto.