|
Boost : |
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
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk