Boost logo

Boost :

From: Fernando Cacciola (fcacciola_at_[hidden])
Date: 2003-02-25 20:36:54

"David B. Held" <dheld_at_[hidden]> escribió en el mensaje
> I think optional might be perfect for an issue I have, but there is one
> catch.
> I have a polymorphic hierarchy that I would like to use with optional, but
> optional<Base> is not a base of optional<Derived>. Of course, this isn't
> really a problem with optional, par se, but any suggestions on how to
> pointers to optional<T> when T is polymorphic would be appreciated.
> I know I can use aggregation like so:
> class Base
> {
> virtual ~Base() { }
> };
> template <typename T>
> class PolyOptional : public Base
> {
> optional<T> value_;
> };
> and then just store Base*, but this requires explicit run-time checking of
> types which would otherwise be automatic with pointers to T instead of
> optional<T>. If this is the only solution, so be it; but any clever
> alternatives are welcome.
> Dave
I think I have bad news...
Let me see:


struct B { virtual ~B() ; } ;
struct D : B {} ;

You can have optional<B> and optional<D>; but as you say,
they are not inheritance related.

You would like to be dealing with:

optional<B>* and optional<D>*

but you can do this as well, so I figure that what you really need
is a 'dynamic-type preserving' conversion between these optionals.
Something that would allow the following:

D dval ;
optional<D> dopt(dval);
optional<B> bopt ( optional_cast<B>(dopt) ) ;
optional<D> dopt2 ( optional_cast<D>(bopt) ) ;

assert ( dval == *dopt2);

Is this what you need?

If it is, I'm afraid it's not possible:

The problem is that even though the conversion will succeed
(it would probably work with the current optional as it is now),
it will inevitably _slice_.

The reason is that optional<B> will get exactly the B subobject
within D and there's no way to get back the rest of D from the B
subobject alone.

AFAICT, this can only be done with pointers because the shallow copy
semantics of pointers is which retains the dynamic type (that is, the
object is always the same, you just refer to different parts of it).
This can't be done with value semantics, unless not if you don't cheat and
traffic always the most derived object by-value.

I think that a solution which uses the PolyOptional<T> technique
is the only way to go.

BTW, that technique is essentialy the same one used by boost::any,
thus, you can store the different optionals in a 'any' object
and traffic the 'anies' instead.


Fernando Cacciola

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