Boost logo

Boost :

From: Larry Evans (jcampbell3_at_[hidden])
Date: 2002-06-24 13:52:04


Peter Dimov wrote:

> From: "Markus Schöpflin" <markus.schoepflin_at_[hidden]>
> > Peter Dimov wrote:
> > >
> > > From: "Markus Schöpflin" <markus.schoepflin_at_[hidden]>
> > > > Hello all,
> > > >
> > > > I have a problem with MSVC6 and shared_ptr. The compiler
> > > > is hopelessly confused by the template constructor:
> > > >
> > > > template<typename Y> explicit shared_ptr(Y * p)
> > > >
> > > > As a result, it fails to compile:
> > > >
> > > > boost::shared_ptr<int> p(0);
> > >
> > > This is as it should be. Either use the default constructor, or cast the
> > > zero to the correct pointer type.
> >
> > Ok, thanks for the clarification. Is there anywhere some design
> > rationale besides the FAQ where I can look up what should work
> > and what not and why it works the way it does?
>
> First let me clarify that this is not a problem with MSVC 6. 'Y *' can not
> be deduced from '0'.
>
> No, there is no rationale document yet. Sorry.
>
> The reason that the zero initialization doesn't work (1.28+) is that the two
> constructors are subtly different; ...
>
> > For me this behaviour is kind of surprising as auto_ptr does
> > have such a constructor.
>
> ... in the auto_ptr/scoped_ptr case, the default constructor _is_
> zero-initialization. shared_ptr's default constructor, however, does not
> require a complete type, and does not invoke 'delete' on destruction. The
> constructor that takes a raw pointer does require a complete type for the
> pointed-to object, and does invoke 'delete p' on destruction, where 'p' is
> the value passed to the constructor, complete with its original type.
>
> So if you say
>
> shared_ptr<void> px(static_cast<X*>(0));
>
> when 'px' is destructed, it will invoke
>
> delete static_cast<X*>(0);
>
> I could have made the simple case
>
> shared_ptr<int> px(0);
>
> work, but it's better not to; it is important to understand the difference.
> And of course,
>
> shared_ptr<void> px(0);
>
> won't work anyway, since void is incomplete.

What if, in case of px(0), you set the counted_base* shared_count::pi_=0?
Then:

    shared_count & shared_count::operator= (shared_count const & r) // nothrow
    {
        counted_base * tmp = r.pi_;
        if( !r.is_null() )tmp->add_ref();
        if( !is_null() )pi_->release();
        pi_ = tmp;

        return *this;
    }
    shared_count::~shared_count() // nothrow
    {
        if( !is_null() ) pi_->release();
    }
and make appropriate checks elsewhere where pi_ may be null?

I've got this to run, and work OK. I don't know how thorough my
tests are :(.


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