Boost logo

Boost Users :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-10-09 08:18:53


Ricardo Capurro wrote:
> Hello,
>
> We are really very happy and impressed with boost's smart_pointers,
> and we found the section "Smart Pointer Programming Techniques"
> (http://www.boost.org/libs/smart_ptr/sp_techniques.html) in boost
> smart_pointer documentation very useful, but we are having this
> problem:
>
> We have two classes X and Y, and each object of class X holds an
> object of class Y, and we need to implement a method in class X to get a
> shared_ptr<Y> so we can access Y instance inside X, and we need that
> X objects (that are too referenced by shared_ptr<X>) don't be deleted
> until all references to the Y object are destroyed. See the problem
> in this code:
>
> class Y {};
>
> class X : public enable_shared_from_this<X> {
>
> Y y;
>
> public:
>
> shared_ptr<Y> ptr_y(); // Oops, how do we do here???
>
> };
>
>
>
> Our first approach was "Using a shared_ptr to hold a pointer to a
> statically allocated object"
> (http://www.boost.org/libs/smart_ptr/sp_techniques.html#static), but
> this doesn't work because X objects can be destroyed and we still have
> pointers to contained Y object, so we try a custom deletor like this:

[as in #another_sp]

> And now the problem was resolved but with one little drawback, we are
> not sharing the same counter between shared_ptr<X> and shared_ptr<Y>, so
> start looking boost's code to shange it in a way that it satisfies our
> needs, and we added this constructor to shared_ptr class:
>
> template<class Y,class Z>
>
> shared_ptr(Y* y, shared_ptr<Z> const & z): px(z.px ? y : 0), pn( y ?
> z.pn : detail::shared_count() ) // never throws

[...]

>> Finally our question is:
>>
>> Is there an easyer way to solve our problem?
>>
>> If the answer is yes we want to know it and
>>
>> if the answer is no we want to know if you can enhace shared_ptr to
>> solve this kind of problem.

I think that you have described the various approaches to the problem quite
well. The only alternative that comes to mind is to switch from containment
to inheritance:

class Y {};

class X: public Y, public enable_shared_from_this<X>
{
public:

    shared_ptr<Y> ptr_y()
    {
        return shared_from_this();
    }
};

or

class X: private Y, public enable_shared_from_this<X>
{
public:

    friend class shared_ptr<Y>;

    shared_ptr<Y> ptr_y()
    {
        return shared_from_this();
    }
};

This of course is not a general solution. I have considered a constructor
similar to your proposal... it is unsafe, but powerful. The current design
approach is to provide safer, but more restricted versions, like
static_pointer_cast.

An alternative would be to add

template<class Y>
    shared_ptr(shared_ptr<Y> const & r, T Y::* pm): px(&((*r).*pm)),
pn(r.pn);

but this is still not a general solution.


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net