
From: "Peter Dimov" <pdimov@pdimov.com>
Anyway, I see you'd been preparing your implementation for Boost but it does not seem to have ever made it. That's unfortunate. How come it was abandoned and sent to the fringes of Yahoo archives?
I have a "policy" of not proposing libraries that I don't use. impl_ptr was a nice experiment, but shared_ptr happens to satisfy all my implementation-hiding needs. :-)
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? Then, I guess, you'd have to explicitly write Pimpl(Pimpl const&), Pimpl::op=(), Pimpl::op==(). Something straightforward like template<class T> class Pimpl { public: Pimpl(Pimpl const that) : impl_(new T(*that.impl_)) {} Pimpl& operator=(Pimpl const& that) const { *impl_ = *that.impl_; return *this; } bool operator==(Pimpl const& that) const { return *impl_ = *that.impl_; } private: class Implementation; boost::shared_ptr<Implementation> impl_; }; does not cut it as it does not compile unless Pimpl::Implementation is visible. So, we have to apply the same incomple-type management technique as deployed in shared_ptr and your other impl_ptr. Like template<class T> class Pimpl { public: Pimpl(Pimpl const that) : impl_(trait_->copy(*that.impl_)) {} Pimpl& operator=(Pimpl const& that) const { trait_->assign(*impl_, *that.impl_); return *this; } bool operator==(Pimpl const& that) const { return trait_->compare(*impl_, *that.impl_); } private: class Implementation; boost::shared_ptr<Implementation> impl_; trait* trait_; }; and that seems like a serious hassle unless generalized. So, it feels the Pimpl situation is begging for your impl_ptr. Don't you agree? 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. Ideally, impl_ptr and shared_ptr ought to share the same scaffolding with different deep/shallow-copy policies. It's sad, it has not worked out that way. Getting back to Pimpl, I feel that a thin interface layer on top of shared_ptr or impl_ptr would alleviate much annoyance while writing Pimpls. It can be as simlpe as class Test1 : boost::pimpl<Test1, pointer_semantics> { only Test interface here }; class Test2 : boost::pimpl<Test2, value_semantics> { only Test interface here }; So, I guess, my question is how would you suggest I approach the issue? I'd really like to hear you view on the subject. Best, Vladimir.