Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2003-01-31 07:09:54


From: "David B. Held" <dheld_at_[hidden]>
>
> smart_ptr(P p)
> : storage(p), ownership(p), checking(), conversion()
> { checking::on_init(p) }

smart_ptr(P p)
    : storage(p), ownership(p), checking(p), conversion()
{}

is nicer. Maybe even conversion(p), for consistency. :-)

But that's not what I have in mind. There are a number of pitfalls awaiting
you.

Consider the converting move constructor:

smart_ptr(smart_ptr & rhs)
    : storage(rhs), ownership(rhs), checking(rhs), conversion(rhs)
{}

(template parameters omitted for brevity)

Its purpose is to take ownership away from the auto_ptr-like rhs (you wanted
to support that) and construct a counted_ptr. As storage is constructed
first, it needs to move from rhs.storage; now when ownership throws,
rhs.storage will be left empty, and the object is gone. This is not that big
of a problem... provided that the other rhs policies can handle storage
being zeroed.

Weak pointers are another interesting case, assuming you want to support
them. A weak_ptr storage can't be copied safely, as the pointer may have
been deleted. If you look at shared_ptr::shared_ptr(weak_ptr const &),
you'll see that it copies the count first (its "ownership policy"), and then
proceeds to copy px (its "storage policy"). weak_ptr's converting
constructor does something similar.

Also:

smart_ptr::~smart_ptr()
{
    if (!ownership_policy::release(get_impl(*this)))
    {
        storage_policy::release();
    }
}

It's difficult to supply a get_impl for a weak pointer, since the returned
pointer can be invalidated at any time by a different thread. That's why
weak_ptr doesn't have (no longer has) one.

In short, trying to support auto_ptr, shared_ptr, and weak_ptr will either
destroy the design, or make it stronger. :-)


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