$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Dave Harris (brangdon_at_[hidden])
Date: 2002-04-19 06:46:20
In-Reply-To: <a9n1el$j4u$1_at_[hidden]>
On Thu, 18 Apr 2002 12:57:59 -0500 David B. Held 
(dheld_at_[hidden]) wrote:
> Another thing I'd like to see is what I call a serializable smart 
> pointer. This is just a smart pointer that stores either a pointer or
> an int, so it's like a variant.  I store object IDs, which is what
> I would load into the pointer on initialization, and then do a
> fixup after all relevant objects are loaded.  Right now, I do this in
> a wrapper I wrote, which may be the preferred way to do it.  But
> it seems to me a bit more elegant to do it in the smart pointer
> itself.
> [...]
> If there is a better way to save and load pointers, I'd be glad to
> hear it.
Can you not do the int => pointer fixup on the fly, rather than waiting 
until all objects are loaded? That way the smart pointer never needs to 
store an integer, and the same mechanism can be used for normal pointers.
That is how my local smart pointers work, in conjunction with Microsoft's 
MFC serialisation. Imagine functions like:
    template <typename T>
    CArchive &operator<<( CArchive &ar, const T *p );
    template <typename T>
    CArchive &operator>>( CArchive &ar, T *&p );
where the CArchive keeps a private table which maps object pointers to and 
from integer IDs. The ID is never seen by the client code.
Two caveats. First, my stuff uses intrusive smart pointers, so it is safe 
to convert a smart pointer to a normal one and back again. You don't end 
up with two copies of the count. So it is OK to have code like:
    template <typename T>
    CArchive &operator>>( CArchive &ar, intrusive_ptr<T> &p ) {
        T *raw_p;
        ar >> raw_p;
        p = raw_p;
        return ar;
    }
 
which mixes raw with smart pointers. I imagine with non-intrusive, 
boost-like pointers, you would need to avoid ever exposing the raw 
pointers.
Secondly, the object table in CArchive itself has a reference to the 
object which needs to be accounted for. This is where MFC falls down. 
However, a serialisation scheme written with smart pointers in mind could 
just use the same smart pointers internally.
(The above code is not actual MFC - MFC CArchive was written without 
templates.)
> If this kind of feature just doesn't belong in a smart pointer,
> I'd like to know why (I'm easy to convince, I just need to see a
> good explanation).
If the smart pointer stores the integer ID, it is not possible to have 
multiple concurrent serialisations. The same object will need more than 1 
ID.
Anyway, the table of object pointer => integer ID does not really belong 
in the smart pointer class, in my view. It belongs somewhere like 
CArchive. For example, it is only used during serialisation. People who 
use smart pointers but who don't do serialisation shouldn't be burdened 
with it. On the other hand, dealing with multiple saves of the same object 
is an intrinsic problem of serialisation so it is not practical to make 
serialisation independent of smart pointers.
The main problem I see with this approach is dealing with several 
different kinds of smart pointer, eg instrusive and non-intrusive, within 
the same CArchive object. Perhaps it will be enough to give each kind of 
pointer a different object ID table.
And then of course we have the schema problem. Eg if a class starts life 
with a non-intrusive count, and then later changes to use an intrusive 
count, the CArchive needs to be able to convert old to new while loading. 
-- Dave Harris