On June 10, 2014 4:15:42 AM EDT, Gavin Lambert
On 10/06/2014 14:15, quoth Vladimir Batov:
In my case it's most likely because my interest in and development of my-pimpl has always been driven by the practical need. And it just happened that I never had a need to hide implementation of small, copyable, value-semantics classes. I would start hiding implementations of classes when they were getting big and/or outside of my control... and not easily or non copyable Say, database (in wide sense) records, GUI components. So that deployment pattern was firmly burnt in my brain... it might well be the specificity of the industry I am in as no-one in our dev. team asked for or deployed pimpl::value_semantics. :-)
My use of Pimpl has also been driven by practical need -- the need to avoid recompiling 200+ source files when changing a tiny implementation
detail of one class that happens to be used deep in the object graph. (Compiling can take quite a long time.) Though normally I just do it manually rather than using any framework -- which isn't to say that a framework might not be useful if I had one readily available.
Another common use case of the Pimpl Idiom is to keep implementation details in a dynamic library (shared object or DLL) for dynamically loaded extensions. Still another is to hide platform specifics. (Chief among those would be avoiding the need to include windows.h.)
But the way you're phrasing things above still sounds to me like we're still coming at things from different perspectives.
To me, any given instance of a class (eg. Book) is *always* a value, and has value semantics. This doesn't imply that it's small or copyable --
you can mark classes as movable only or non-copyable/movable.
The Handle/Body Idiom provides a handle class that manages a pointer to an instance of an implementation class. Normally, multiple handle objects can refer to the same body object, so reference counting is implied. Pimpl is a degenerate case with only one handle per body.
If something wants to have a reference to that instance (pointer semantics), then it declares a pointer, reference, or smart pointer instance that refers to the other object. (Note that a smart pointer is itself a value-semantics instance that happens to have pointer-semantics referring to another object as well.) It's left up to the consumer to decide what kind of pointer to use, based on how they plan to use it.
Both approaches are appropriate.
On occasion I've made a class that mandates specific pointer-semantics only (usually because it uses shared_from_this()), but it does this by having a private constructor, deleted copy constructor, and a public factory method that returns a shared_ptr<X>, such that it's not possible to get a non-shared instance from outside. Internally it's still a value object.
Also valid, but not more so.
But the concept of referencing/pointing is separated from the class itself, which is where our perspectives differ, I think.
One library can support both, however. ___ Rob (Sent from my portable computation engine)