"David Abrahams" <[EMAIL PROTECTED]> wrote in message
[EMAIL PROTECTED]">news:[EMAIL PROTECTED]...
> > [...]
> > Unfortunately, StoragePolicy doesn't know when other c'tors have
> > failed.  The only one who does is smart_ptr, which is why it seems
> > I have to either A) use a function try block to inform StoragePolicy
> > that someone else has failed, and clean up appropriately,
>
> Why not just arrange for StoragePolicy to be the first constructed?

smart_ptr(T* p)
    : storage(p), ownership(p), conversion(), checking()
{ ... }

Suppose storage(p) succeeds, but ownership(p) throws (such as while
allocating a count).  You can't rely on ~storage() to do cleanup, because
storage doesn't know what the ownership strategy is.  It only knows
about storage.  Here's what ~smart_ptr() looks like:

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

So you see, storage_policy must be told when to do cleanup by
smart_ptr (that's the principle of orthogonal policies).  It's easy
enough to write storage_policy::storage_policy(T* p) to clean up
after itself if *it* throws.  But getting it to clean up after *another*
policy is the trick.  Obviously, if one of the other c'tors throws,
~smart_ptr() never gets called, so how do we tell storage_policy
that a failure occurred, and it needs to clean up?  The only way I
can see is to use a function try block:

smart_ptr(T* p)
try
    : storage_policy(p), ownership(p), conversion(), checking()
{ ... }
catch
{
    storage_policy::destroy();
}

Unfortunately, that's totally Greek to bcc 5.5 (and probably vc++,
though I don't have access to it right now), not to mention that it
requires storage_policy(p) to be no-throw.

> > or B) not use initializer lists, and do all the work in the c'tor
> > body of smart_ptr.
>
> I don't see how B can work; the resource will be unmanaged at
> least until the body is entered, while all the bases and members
> are constructed.

That can only work if the default c'tors are no-throw, which would
mean special-casing ref_counted to not allocate a count until it
actually receives a pointer.  But it would also make the rest of the
functions in ref_counted bulkier because now you have to detect a
null count pointer.  Otherwise, you would have to set the count
pointer to null, and have the body of smart_ptr ask ref_counted if
he was built properly.  Quite messy.  I don't see any nice solutions
to this problem.

Dave



_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Reply via email to