canonical up-cast idiom for smart pointers?

T

Tim H

I'm wondering if there is a way to do this properly. I feel like I am
missing something.

I have two distinct classes. They don't have much at all in common.
I want a vector-like container that contains smart pointers
(boost::shared_ptr or similar) to a set of these two classes and keeps
them sorted wrt each other.

For example if I insert ClassA, ClassA, ClassB, ClassA, ClassB in that
order, I want to re-visit them in that same order when I iterate
later.

My first thought was to make an artificial base class that has a
'type' argument indicating which "derived" type was stored. Then a
simple vector< shared_ptr<Base> > gets me my objects back. The
problem, of course, is that I get back pointers to the Base type.

Is there an idiomatic way to go from shared_ptr<Base> to
shared_ptr<Derived> ? I note that the compiler happily goes the other
way automatically.

Or maybe there is another idiomatic way to store this data? I can
think of a half-dozen ways (seperate vectors with a third switcher
vector, etc), but they all seem dirty.

Is there a better way?

Tim
 
R

roy axenov

I have two distinct classes. They don't have much at all
in common.
I want a vector-like container that contains smart
pointers (boost::shared_ptr or similar) to a set of these
two classes and keeps them sorted wrt each other.

You're contradicting yourself. If those two classes don't
have much in common, why are you trying to store them in
the same vector? Presumably, because you want to iterate
over the vector, retrieve the objects and do-something with
them depending on what they are. The point is,
do-something-after-being-retrieved-from-a-vector is exactly
what they have in common then, even if the implementations
vastly differ between the classes.

And that's exactly the thing that belongs to an abstract
base class that both your classes should inherit from.
For example if I insert ClassA, ClassA, ClassB, ClassA,
ClassB in that order, I want to re-visit them in that
same order when I iterate later.

And do-something, right? So instead of (pseudocode):

if ( ( * base_object ) is-a ClassA object )
base_object -> do_some_ClassA_stuff ( ) ;
else
base_object -> do_some_ClassB_stuff ( ) ;

....make that:

baseObject -> do_stuff ( ) ;

And let the objects themselves worry about what exactly
should be done.
My first thought was to make an artificial base class
that has a 'type' argument indicating which "derived"
type was stored.

And why would you want to know? Let the objects handle the
differences. Why implement the polymorphism by hand if you
can have the compiler handle the grisly details for you?
Is there an idiomatic way to go from shared_ptr<Base> to
shared_ptr<Derived> ?

Why would you want to? If the objects are so vastly
different you can't do with a pointer to a base class, they
shouldn't be stored together. If they have something in
common that allows them to be processed together, that
something-in-common belongs to the base class, in which
case the base class pointer should suffice (and
implementations will handle the differences).

All in all, it looks like more of a design problem than a
C++ problem to me. Perhaps you should consult the gurus in
comp.object.
 
K

Kai-Uwe Bux

Tim H wrote:

[snip]
Is there an idiomatic way to go from shared_ptr<Base> to
shared_ptr<Derived> ?

There are tr1::dynamic_pointer_cast<> and tr1::static_pointer_cast<>.

Note that the need for up-casting may indicate a design problem.


Best

Kai-Uwe Bux
 
T

Tim H

You're contradicting yourself. If those two classes don't
have much in common, why are you trying to store them in
the same vector?

It's a filesystem-like structure. Think directories and files. There
are a whole host of things you do with files that don't apply to
directories, and there are a whole host of things you do with
directories that you don't do to files. And yet, when you run 'ls'
you see them intermixed.

This is not a perfect analogy for the problem at hand, but it's
close. These two (for now, could be more) classes are distinct, but I
want to store them in the order they were discovered wrt each other.
Why would you want to?

I don't want to, but that's why I am here. This feels like wrong
design, and I am looking for a better answer. That said, it should be
*possible* because I know through my own meta-data that it's safe, and
in the end it's just a pointer.
All in all, it looks like more of a design problem than a
C++ problem to me. Perhaps you should consult the gurus in
comp.object.

Might just do that. Thanks.

Tim
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top