
Vladimir Batov: ...
That's fair enough. I myself certainly always use shared_ptr-based Pimpl. However, due to specificity of my task I tend to use Pimpls with pointer semantics only. In this discussion thread as soon as I mentioned Pimpl people asked for value semantics and I believe that's reasonable. Are you saying you've been using shared_ptr for Pimpls with value semantics?
My use cases so far have always been of the form // foo.hpp: namespace foo { class impl; typedef shared_ptr<impl> handle; handle create( ... ); void operation( handle, ... ); } // foo.cpp: #include "foo.hpp" #include <windows.h> // this is why we bother with a pimpl ... <windows.h> is just an example, of course, there are many other headers that one would like to hide behind a pimpl. This also creates a stable binary interface. I think I had a need for a value-based pimpl once or twice, but I don't remember how I handled it. Probably the old-fashioned way.
Unfortunately, neither your impl_ptr nor Alan Griffith grin_ptr seem to be complete. Alan's implementation is very basic and does not seem to handle run-time polymorphic classes. Your impl_ptr is better in that regard and closer to shared_ptr (for obvious reasons :-)). However, dynamic_traits extends incomplete-type management only onto copy when I feel it needs to do the same for assignment and comparison. I do not feel impl_ptr's approach to assignment via deletion and copy construction is 100% kosher.
An interesting question. I haven't given assignment much thought since in the Old C++ Days (before move), if you were willing to expose a heavy copy constructor that hits the heap, once could reasonably conclude that the class (or rather the container it's being put in) is not performance-critical. So implementing assignment in terms of copy construction wasn't that bad, efficiency-wise, and saved the user from having to make the implementation class Assignable.