Connecting Tech Pros Worldwide Help | Site Map

Storing different types in container

tuvok
Guest
 
Posts: n/a
#1: Jul 23 '05
How can objects of different types be stored in a collection?
For example:

struct S1 { /*...*/ };
struct S2 { /*...*/ };
struct Sn { /*...*/ };

template<typename T> class X
{
public:
T data;
X() {}
//...
};

//...
X<S1> x1;
X<S2> x2;
X<Sn> xn;

Can these objects be stored in the same collection class (for example in a vector or map)?



ben
Guest
 
Posts: n/a
#2: Jul 23 '05

re: Storing different types in container


[color=blue]
>
> Can these objects be stored in the same collection class (for example in a[/color]
vector or map)?

No unless you try to use dangerous vector<void*>.

ben


Jonathan Turkanis
Guest
 
Posts: n/a
#3: Jul 23 '05

re: Storing different types in container


ben wrote:[color=blue][color=green]
>> Can these objects be stored in the same collection class (for
>> example in a vector or map)?[/color]
>
> No unless you try to use dangerous vector<void*>.[/color]

Or the alluring vector<boost::any> ;-)
[color=blue]
> ben[/color]

Jonathan


Larry I Smith
Guest
 
Posts: n/a
#4: Jul 23 '05

re: Storing different types in container


tuvok wrote:[color=blue]
> How can objects of different types be stored in a collection?
> For example:
>
> struct S1 { /*...*/ };
> struct S2 { /*...*/ };
> struct Sn { /*...*/ };
>
> template<typename T> class X
> {
> public:
> T data;
> X() {}
> //...
> };
>
> //...
> X<S1> x1;
> X<S2> x2;
> X<Sn> xn;
>
> Can these objects be stored in the same collection class (for example in a vector or map)?
>
>
>[/color]

IF they all derive from the same base class (e.g. circle, rectangle,
triangle all derive from shape), then you can store them as
objects of the base class (e.g. as 'shape'). Otherwise - no.

Regards,
Larry
tuvok
Guest
 
Posts: n/a
#5: Jul 23 '05

re: Storing different types in container


"Larry I Smith" <larryXiXsmith@verizon.net> wrote[color=blue]
> tuvok wrote:[color=green]
> > How can objects of different types be stored in a collection?
> > For example:
> >
> > struct S1 { /*...*/ };
> > struct S2 { /*...*/ };
> > struct Sn { /*...*/ };
> >
> > template<typename T> class X
> > {
> > public:
> > T data;
> > X() {}
> > //...
> > };
> >
> > //...
> > X<S1> x1;
> > X<S2> x2;
> > X<Sn> xn;
> >
> > Can these objects be stored in the same collection class (for example in a vector or map)?
> >[/color]
>
> IF they all derive from the same base class (e.g. circle, rectangle,
> triangle all derive from shape), then you can store them as
> objects of the base class (e.g. as 'shape'). Otherwise - no.[/color]

Something like the following?

template<typename T> class X : public B { /* see above */ }

How would this be added to a std::vector?


Artie Gold
Guest
 
Posts: n/a
#6: Jul 23 '05

re: Storing different types in container


Larry I Smith wrote:[color=blue]
> tuvok wrote:
>[color=green]
>>How can objects of different types be stored in a collection?
>>For example:
>>
>>struct S1 { /*...*/ };
>>struct S2 { /*...*/ };
>>struct Sn { /*...*/ };
>>
>>template<typename T> class X
>>{
>> public:
>> T data;
>> X() {}
>> //...
>>};
>>
>>//...
>>X<S1> x1;
>>X<S2> x2;
>>X<Sn> xn;
>>
>>Can these objects be stored in the same collection class (for example in a vector or map)?
>>
>>
>>[/color]
>
>
> IF they all derive from the same base class (e.g. circle, rectangle,
> triangle all derive from shape), then you can store them as
> objects of the base class (e.g. as 'shape'). Otherwise - no.
>[/color]
Erm...

You can store *pointers* to them (but not the objects themselves) as
*pointers to the base class* in this case; of course in that case, you'd
have to manage the objects' lifetimes manually.

HTH,
--ag
--
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays
Larry I Smith
Guest
 
Posts: n/a
#7: Jul 23 '05

re: Storing different types in container


Artie Gold wrote:[color=blue]
> Larry I Smith wrote:[color=green]
>> tuvok wrote:
>>[color=darkred]
>>> How can objects of different types be stored in a collection?
>>> For example:
>>>
>>> struct S1 { /*...*/ };
>>> struct S2 { /*...*/ };
>>> struct Sn { /*...*/ };
>>>
>>> template<typename T> class X
>>> {
>>> public:
>>> T data;
>>> X() {}
>>> //...
>>> };
>>>
>>> //...
>>> X<S1> x1;
>>> X<S2> x2;
>>> X<Sn> xn;
>>>
>>> Can these objects be stored in the same collection class (for example
>>> in a vector or map)?
>>>
>>>
>>>[/color]
>>
>>
>> IF they all derive from the same base class (e.g. circle, rectangle,
>> triangle all derive from shape), then you can store them as
>> objects of the base class (e.g. as 'shape'). Otherwise - no.
>>[/color]
> Erm...
>
> You can store *pointers* to them (but not the objects themselves) as
> *pointers to the base class* in this case; of course in that case, you'd
> have to manage the objects' lifetimes manually.
>
> HTH,
> --ag[/color]

Yes, you are correct. Base class pointers only...

Larry
Jason Heyes
Guest
 
Posts: n/a
#8: Jul 23 '05

re: Storing different types in container


"Larry I Smith" <larryXiXsmith@verizon.net> wrote in message
news:WHPqe.418$1q5.323@trnddc02...[color=blue]
> Artie Gold wrote:[color=green]
>> Larry I Smith wrote:[color=darkred]
>>> tuvok wrote:
>>>
>>>> How can objects of different types be stored in a collection?
>>>> For example:
>>>>
>>>> struct S1 { /*...*/ };
>>>> struct S2 { /*...*/ };
>>>> struct Sn { /*...*/ };
>>>>
>>>> template<typename T> class X
>>>> {
>>>> public:
>>>> T data;
>>>> X() {}
>>>> //...
>>>> };
>>>>
>>>> //...
>>>> X<S1> x1;
>>>> X<S2> x2;
>>>> X<Sn> xn;
>>>>
>>>> Can these objects be stored in the same collection class (for example
>>>> in a vector or map)?
>>>>
>>>>
>>>>
>>>
>>>
>>> IF they all derive from the same base class (e.g. circle, rectangle,
>>> triangle all derive from shape), then you can store them as
>>> objects of the base class (e.g. as 'shape'). Otherwise - no.
>>>[/color]
>> Erm...
>>
>> You can store *pointers* to them (but not the objects themselves) as
>> *pointers to the base class* in this case; of course in that case, you'd
>> have to manage the objects' lifetimes manually.
>>
>> HTH,
>> --ag[/color]
>
> Yes, you are correct. Base class pointers only...
>[/color]

Write a class to encapsulate the base class and hide the management of
object lifetime using boost::shared_ptr. Objects (not pointers to objects)
of the base-encapsulating class can be stored in a std::vector like any
other object.


tuvok
Guest
 
Posts: n/a
#9: Jul 23 '05

re: Storing different types in container


"Jason Heyes" <jasonheyes@optusnet.com.au> wrote[color=blue]
> "Larry I Smith" <larryXiXsmith@verizon.net> wrote in message[color=green]
> > Artie Gold wrote:[color=darkred]
> >> Larry I Smith wrote:
> >>> tuvok wrote:
> >>>
> >>>> Can these objects be stored in the same collection class (for example
> >>>> in a vector or map)?
> >>>>
> >>> IF they all derive from the same base class (e.g. circle, rectangle,
> >>> triangle all derive from shape), then you can store them as
> >>> objects of the base class (e.g. as 'shape'). Otherwise - no.
> >>>
> >> Erm...
> >>
> >> You can store *pointers* to them (but not the objects themselves) as
> >> *pointers to the base class* in this case; of course in that case, you'd
> >> have to manage the objects' lifetimes manually.
> >>
> >> HTH,
> >> --ag[/color]
> >
> > Yes, you are correct. Base class pointers only...
> >[/color]
>
> Write a class to encapsulate the base class and hide the management of
> object lifetime using boost::shared_ptr. Objects (not pointers to objects)
> of the base-encapsulating class can be stored in a std::vector like any
> other object.[/color]

Will then the right virtual functions be invoked?


ben
Guest
 
Posts: n/a
#10: Jul 23 '05

re: Storing different types in container


In addtion, you need all the classes to be polymorphic to be able to cast
from void* to the appropriate type.

ben
[color=blue]
>
> No unless you try to use dangerous vector<void*>.
>
> ben
>
>[/color]


Jason Heyes
Guest
 
Posts: n/a
#11: Jul 23 '05

re: Storing different types in container


"tuvok" <520001085531-0001@t-online.de> wrote in message
news:d8gl6p$m5v$05$1@news.t-online.com...[color=blue]
> "Jason Heyes" <jasonheyes@optusnet.com.au> wrote[color=green]
>> "Larry I Smith" <larryXiXsmith@verizon.net> wrote in message[color=darkred]
>> > Artie Gold wrote:
>> >> Larry I Smith wrote:
>> >>> tuvok wrote:
>> >>>
>> >>>> Can these objects be stored in the same collection class (for
>> >>>> example
>> >>>> in a vector or map)?
>> >>>>
>> >>> IF they all derive from the same base class (e.g. circle, rectangle,
>> >>> triangle all derive from shape), then you can store them as
>> >>> objects of the base class (e.g. as 'shape'). Otherwise - no.
>> >>>
>> >> Erm...
>> >>
>> >> You can store *pointers* to them (but not the objects themselves) as
>> >> *pointers to the base class* in this case; of course in that case,
>> >> you'd
>> >> have to manage the objects' lifetimes manually.
>> >>
>> >> HTH,
>> >> --ag
>> >
>> > Yes, you are correct. Base class pointers only...
>> >[/color]
>>
>> Write a class to encapsulate the base class and hide the management of
>> object lifetime using boost::shared_ptr. Objects (not pointers to
>> objects)
>> of the base-encapsulating class can be stored in a std::vector like any
>> other object.[/color]
>
> Will then the right virtual functions be invoked?
>[/color]

Absolutely. For example, say Animal is your base and Animal has a virtual
function called make_noise. Here is the encapsulating class (called a
handle) for the Animal base class:

class AnimalHandle
{
boost::shared_ptr<Animal> animal_ptr;

public:
AnimalHandle() : animal_ptr(new Animal()) { }

void make_noise() const { animal_ptr->make_noise(); }
};

You can store AnimalHandle objects in std::vector. You don't need to store
pointers to AnimalHandle.


Axter
Guest
 
Posts: n/a
#12: Jul 23 '05

re: Storing different types in container


tuvok wrote:[color=blue]
> How can objects of different types be stored in a collection?
> For example:
>
> struct S1 { /*...*/ };
> struct S2 { /*...*/ };
> struct Sn { /*...*/ };
>
> template<typename T> class X
> {
> public:
> T data;
> X() {}
> //...
> };
>
> //...
> X<S1> x1;
> X<S2> x2;
> X<Sn> xn;
>
> Can these objects be stored in the same collection class (for example in a vector or map)?[/color]

You can create a Heterogeneous Container if all the types have a
commone method or data type.
A Heterogeneous Container is a container of different types that have
NO common base type.

This method requires a wrapper class, that gives access to the common
method and/or data.

See following links for example code:
http://code.axter.com/HeterogeneousContainer1.cpp
http://code.axter.com/HeterogeneousContainer2.cpp
http://code.axter.com/HeterogeneousContainer3.cpp

Some compilers may have problems with the last example.

Panjandrum
Guest
 
Posts: n/a
#13: Jul 23 '05

re: Storing different types in container


Axter wrote:[color=blue]
> You can create a Heterogeneous Container if all the types have a
> commone method or data type.
> A Heterogeneous Container is a container of different types that have
> NO common base type.
>
> This method requires a wrapper class, that gives access to the common
> method and/or data.
>
> See following links for example code:
> http://code.axter.com/HeterogeneousContainer1.cpp
> http://code.axter.com/HeterogeneousContainer2.cpp
> http://code.axter.com/HeterogeneousContainer3.cpp
>
> Some compilers may have problems with the last example.[/color]

Some humans may have problems with contrived designs.

ben
Guest
 
Posts: n/a
#14: Jul 23 '05

re: Storing different types in container


> Some humans may have problems with contrived designs.[color=blue]
>[/color]

It's still inheritance, only that the template generates function code every
time you AddToPocket(), which bridges the heterogeneous objects to a common
base.

ben


Phil Endecott
Guest
 
Posts: n/a
#15: Jul 23 '05

re: Storing different types in container


tuvok wrote:[color=blue]
> How can objects of different types be stored in a collection?[/color]

http://www.boost.org/doc/html/any.html
Panjandrum
Guest
 
Posts: n/a
#16: Jul 23 '05

re: Storing different types in container


Phil Endecott wrote:[color=blue]
> http://www.boost.org/doc/html/any.html[/color]

Repost

Jonathan Turkanis
Guest
 
Posts: n/a
#17: Jul 23 '05

re: Storing different types in container


ben wrote:[color=blue]
> In addtion, you need all the classes to be polymorphic to be able to
> cast from void* to the appropriate type.[/color]

All that's needed is a way to remember the original type. This can be done
several ways.

You can't dynamic_cast from a void*.
[color=blue]
> ben[/color]

Jonathan


Larry I Smith
Guest
 
Posts: n/a
#18: Jul 23 '05

re: Storing different types in container


Jason Heyes wrote:[color=blue]
> "tuvok" <520001085531-0001@t-online.de> wrote in message
> news:d8gl6p$m5v$05$1@news.t-online.com...[color=green]
>>"Jason Heyes" <jasonheyes@optusnet.com.au> wrote[color=darkred]
>>>"Larry I Smith" <larryXiXsmith@verizon.net> wrote in message
>>>>Artie Gold wrote:
>>>>>Larry I Smith wrote:
>>>>>>tuvok wrote:
>>>>>>
>>>>>>>Can these objects be stored in the same collection class (for
>>>>>>>example
>>>>>>>in a vector or map)?
>>>>>>>
>>>>>>IF they all derive from the same base class (e.g. circle, rectangle,
>>>>>>triangle all derive from shape), then you can store them as
>>>>>>objects of the base class (e.g. as 'shape'). Otherwise - no.
>>>>>>
>>>>>Erm...
>>>>>
>>>>>You can store *pointers* to them (but not the objects themselves) as
>>>>>*pointers to the base class* in this case; of course in that case,
>>>>>you'd
>>>>>have to manage the objects' lifetimes manually.
>>>>>
>>>>>HTH,
>>>>>--ag
>>>>Yes, you are correct. Base class pointers only...
>>>>
>>>Write a class to encapsulate the base class and hide the management of
>>>object lifetime using boost::shared_ptr. Objects (not pointers to
>>>objects)
>>>of the base-encapsulating class can be stored in a std::vector like any
>>>other object.[/color]
>>Will then the right virtual functions be invoked?
>>[/color]
>
> Absolutely. For example, say Animal is your base and Animal has a virtual
> function called make_noise. Here is the encapsulating class (called a
> handle) for the Animal base class:
>
> class AnimalHandle
> {
> boost::shared_ptr<Animal> animal_ptr;
>
> public:
> AnimalHandle() : animal_ptr(new Animal()) { }
>
> void make_noise() const { animal_ptr->make_noise(); }
> };
>
> You can store AnimalHandle objects in std::vector. You don't need to store
> pointers to AnimalHandle.
>
>[/color]

You should advise the OP that Boost is not part of the C++ Standard.
It's an add-on that will have to be obtained/installed.

http://www.boost.org/

Larry
Closed Thread