Boost logo

Boost :

From: Vladimir Batov (batov_at_[hidden])
Date: 2007-10-13 22:27:21


From: "Peter Dimov" <pdimov_at_[hidden]>

>> 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.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk