Boost logo

Boost :

From: George A. Heintzelman (georgeh_at_[hidden])
Date: 2002-07-30 14:08:12

> > class X { int x; };
> > class Y { int y; };
> > class Derived: public X, public Y {};
> >
> > The layout of Derived is going to be X::x followed by Y::y (or
> > vice-versa). If you do:
> >
> > ptr<Derived> pd = new Derived (whatever syntax) ;
> > ptr<Y> py = pd;
> > ptr<X> px = pd;
> >
> > one of py, px is going to point into the middle of the Derived object;
> > and then the imputed reference count location will be *wrong*. So
> > either you need to forbid ptr's to multiply-derived objects or forbid
> > conversions to base classes inside ptr's. Either of these is a pretty
> > serious price to pay, IMHO.
> Well it is easy to fix but haven't done it yet. You just implement some
> sort of template constructor which will cast the offset properly with
> static_cast<>s directly or assignments assertions.

Er, how, while keeping sizeof(ptr<Y>) == sizeof(Y *))?

A plain old Y object, we have a ptr<Y>, containing some pointer P. One
reasonable implementation is:
      | Ref count
P -> +----------------
      | Y::y

Now, for a Derived object, which we now make a ptr<Y> for. Where to
place the pointer P for this, A or B?
      | Ref count
A -> +----------------
      | X::x
B -> +----------------
      | Y::y

If you place it at A, then you get X::x when you refer to py->y, which
is clearly wrong. If you place it at B, then when the ptr<Y> goes out
of scope, you will decrement X::x instead of the Ref count. You can't
define a ptr<Y> that works the same way for both a real Y object and a
Y object that is part of a Derived object.

Hence the need for 2 pointers, wherever you put the refcount. You can,
of course, attach the ref count to the allocation with an operator new
if you like...

If you claim you have a solution that keeps sizeof(ptr<X>) == sizeof(X
*), you'll have to demonstrate it more convincingly.

George Heintzelman

Boost list run by bdawes at, gregod at, cpdaniel at, john at