Re: [boost] [pimpl] Proposal. Determining interest.

Inherited Pimpls
sdfsd
Polymorphic Implementations
sdfs
I'd very much like to see those sections, or even only how you'd go about
re-using a pimpl_ptr from a base class, inheriting Derived::Impl from Base::Impl.?
From outside Test is an ordinary C++ class and NOT a pointer or anything
It has to be remembered that Pimpl idiom is about implementation hiding, i.e. it's about implementation and it's about hiding. It's not about making a class to behave as a pointer -- that is done by shared_ptr and done beautifully. A Pimpl-based class is by all means an ordinary class. The fact that its implementation is done in pimpl fashion is an implementation detail and is irrelevant when one inherits from that class. Therefore, as far as inheriting from a Pimpl-based class is concerned, there is not much to it. That is, class Test : public pimpl<Test>::pointer_semantics { }; like, say, shared_ptr<Test>. So, to inherit from it class Derived : public Test { }; Certainly it is unreasonable to expect all the perks that pimpl<> provided while we built Test to percolate to Derived. As far as "inheriting Derived::Impl from Base::Impl", then I've been doing pimpl<Base>::implementation { }; pimpl<Derived>::implementation : pimpl<Base>::implementation { }; on one occasion. So far, my experience is that you cannot make much use of it (like Test being polymorphic and housing Derived implementation instead)... unless you are prepared to forgo implementation hiding -- something the Pimpl is deployed for in the first place. If you do not care for implementation hiding, then I'd suggest going with shared_ptr instead. Thanks, Vladimir.

On Thursday 01 November 2007 20:12, Vladimir.Batov@wrsa.com.au wrote:
It has to be remembered that Pimpl idiom is about implementation hiding, i.e. it's about implementation and it's about hiding. It's not about making a class to behave as a pointer -- that is done by shared_ptr and done beautifully. A Pimpl-based class is by all means an ordinary class. The fact that its implementation is done in pimpl fashion is an implementation detail and is irrelevant when one inherits from that class.
I respectfully disagree. If you have a class library with a fairly deep class hierarchy, re-using the pimpl_ptr from a base class (and inheriting Private classes from each other), is a very valid optimization, both in time and space. Taking Qt (KDE has of course a very similar technique) as an example, we have QTextBrowser -> QTextEdit -> QAbstractScrollArea -> QWidget -> QObject All of which are pimpl'ed for binary compatibility reasons. Unless you can inherit QTextBrowserPrivate from QTextEditPrivate, and stuff it into QObject::pimpl, there's a space overhead (4*sizeof(void*)) + a memory management overhead that could (and should) be avoided. Implementation hiding in this case means hiding from the user of the library, not from other components of the library. Doing this also helps establishing 'module' access rights, otherwise lacking in C++, but useful for scaling to very large systems. E.g., I could make members of QObjectPrivate virtual, and therefore provide protected extension vectors that are only accessible from the 'module', ie. from within the same library. Any pimpl_ptr proposal that does not adequately deal with this (common, in my line of work) scenario wouldn't meet my personal generality requirements. Thanks, Marc -- Marc Mutz -- marc@klaralvdalens-datakonsult.se, mutz@kde.org Klarälvdalens Datakonsult AB, Platform-independent software solutions

Marc, I have re-read the Bridge pattern in GoF Pattern Bible. Their example is just what you describe in your example. I agree that having/supporting two separate hierarchies is an elegant solution to a few problems. Let me think how pimpl<> might support that. Best, Vladimir. Marc Mutz wrote:
On Thursday 01 November 2007 20:12, Vladimir.Batov@wrsa.com.au wrote:
It has to be remembered that Pimpl idiom is about implementation hiding, i.e. it's about implementation and it's about hiding. It's not about making a class to behave as a pointer -- that is done by shared_ptr and done beautifully. A Pimpl-based class is by all means an ordinary class. The fact that its implementation is done in pimpl fashion is an implementation detail and is irrelevant when one inherits from that class.
I respectfully disagree.
If you have a class library with a fairly deep class hierarchy, re-using the pimpl_ptr from a base class (and inheriting Private classes from each other), is a very valid optimization, both in time and space. Taking Qt (KDE has of course a very similar technique) as an example, we have QTextBrowser -> QTextEdit -> QAbstractScrollArea -> QWidget -> QObject All of which are pimpl'ed for binary compatibility reasons. Unless you can inherit QTextBrowserPrivate from QTextEditPrivate, and stuff it into QObject::pimpl, there's a space overhead (4*sizeof(void*)) + a memory management overhead that could (and should) be avoided. Implementation hiding in this case means hiding from the user of the library, not from other components of the library.
Doing this also helps establishing 'module' access rights, otherwise lacking in C++, but useful for scaling to very large systems. E.g., I could make members of QObjectPrivate virtual, and therefore provide protected extension vectors that are only accessible from the 'module', ie. from within the same library.
Any pimpl_ptr proposal that does not adequately deal with this (common, in my line of work) scenario wouldn't meet my personal generality requirements.
Thanks, Marc

Marc, Just uploaded v0.6 which supports building of two separate class hierarchies -- separately for interfaces and for implementations as described in GoF Pattern Bible for the Bridge pattern. The interface hierarchy is built as struct Base : public pimpl<Base>::pointer_semantics {...}; struct Derived : public Base {...} etc. The implementation hierarchy is still hidden and is built as template<> struct pimpl<Base>::implementation {...}; template<> struct pimpl<Derived>::implementation : public pimpl<Base>::implementation {...}; etc. Marc, let me know if that looks right for your purpose as I myself have no use for deep inheritance trees to test them out. Best, Vladimir.
Marc,
I have re-read the Bridge pattern in GoF Pattern Bible. Their example is just what you describe in your example. I agree that having/supporting two separate hierarchies is an elegant solution to a few problems. Let me think how pimpl<> might support that.
Best, Vladimir.

Vladimir Batov wrote:
Marc,
Just uploaded v0.6 which supports building of two separate class hierarchies -- separately for interfaces and for implementations as described in GoF Pattern Bible for the Bridge pattern.
The interface hierarchy is built as
struct Base : public pimpl<Base>::pointer_semantics {...};
struct Derived : public Base {...}
etc.
The implementation hierarchy is still hidden and is built as
template<> struct pimpl<Base>::implementation {...};
template<> struct pimpl<Derived>::implementation : public pimpl<Base>::implementation {...};
etc.
Marc, let me know if that looks right for your purpose as I myself have no use for deep inheritance trees to test them out.
Best, Vladimir.
Marc,
I have re-read the Bridge pattern in GoF Pattern Bible. Their example is just what you describe in your example. I agree that having/supporting two separate hierarchies is an elegant solution to a few problems. Let me think how pimpl<> might support that.
Out of curiosity in this and all other examples of this pimpl library public inheritance is used. Isn't this an implemented in terms (spelled private) of rather than an IS-A (spelled public) relationship? I'm sure there is a technical reason I'm missing. Thanks, Michael Marcin

Out of curiosity in this and all other examples of this pimpl library public inheritance is used. Isn't this an implemented in terms (spelled private) of rather than an IS-A (spelled public) relationship?
I'm sure there is a technical reason I'm missing.
I the examples I build two separate hierarchies -- for interfaces and for implementations. Those examples are to demonstrate pimpl<> deployment for polymorphic classes, i.e. with IS-A kind of relationship. I am not sure where "implemented in terms" comes in as interfaces inherit from interfaces and implementations inherit from implementations. Clearly IS-A as far as I can see. Best, V.

Vladimir Batov wrote:
Out of curiosity in this and all other examples of this pimpl library public inheritance is used. Isn't this an implemented in terms (spelled private) of rather than an IS-A (spelled public) relationship?
I'm sure there is a technical reason I'm missing.
I the examples I build two separate hierarchies -- for interfaces and for implementations. Those examples are to demonstrate pimpl<> deployment for polymorphic classes, i.e. with IS-A kind of relationship. I am not sure where "implemented in terms" comes in as interfaces inherit from interfaces and implementations inherit from implementations. Clearly IS-A as far as I can see.
You consider pimpl part of the interface? Interesting... I've always thought of it as an implementation detail to build compiler firewalls. I.E. any class I've made using the pimpl idiom I could have built the same interface with more external dependencies and heavier compile times.

You consider pimpl part of the interface? Interesting... I've always thought of it as an implementation detail to build compiler firewalls. I.E. any class I've made using the pimpl idiom I could have built the same interface with more external dependencies and heavier compile times.
If your question was about pimpl<> itself, then I misunderstood your question. Although given pimpl<> provides at least some of the public interface it could be considered as such. Although I probably tend to consider it an implementation glue between interface and implementation. To figure out why I inherit publicly from pimpl<> you might like to try inheriting privately (which I never do. I use aggregation insted) and see what functionality becomes unavailable. Best, V.

On Saturday November 3 2007 07:55, Vladimir Batov wrote:
Marc,
Just uploaded v0.6 which supports building of two separate class hierarchies -- separately for interfaces and for implementations as described in GoF Pattern Bible for the Bridge pattern.
The interface hierarchy is built as
struct Base : public pimpl<Base>::pointer_semantics {...};
struct Derived : public Base {...}
etc.
The implementation hierarchy is still hidden and is built as
template<> struct pimpl<Base>::implementation {...};
template<> struct pimpl<Derived>::implementation : public pimpl<Base>::implementation {...};
etc.
Marc, let me know if that looks right for your purpose as I myself have no use for deep inheritance trees to test them out. <snip>
I've been more thinking about the attached scenario. I'm not sure it's worth it, since the savings don't seem to be large compared to hand-written code, and the need to spell out the forwarding Base(implementation*) is a bit ugly (maybe that can be solved in C++0x?), but that should give you the idea. Maybe someone better at template magic than I am can coerce this into a workable thing. The need for verboseness in referring to pimpl<Class>::implementation strikes me as a likely candidate for improvement, e.g. Thanks, Marc -- Marc Mutz - marc@kdab.com, mutz@kde.org - Klarälvdalens Datakonsult AB Platform-independent software solutions - www.kdab.com info@kdab.com
participants (5)
-
Marc Mutz
-
Marc Mutz
-
Michael Marcin
-
Vladimir Batov
-
Vladimir.Batov@wrsa.com.au