Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Templated containers of inherited objects

Reply
Thread Tools

Templated containers of inherited objects

 
 
George Exarchakos
Guest
Posts: n/a
 
      02-16-2007
Hi everyone,

I'd like your help...

Can we have a std::list<BASE> where BASE be the base class of a class
hierarchy? I want to add to this list objects that are inherited from
BASE class but not necessarily the same...

class base {
int x;
};

class child1 : public base {
int d;
};

class child2 : public base {
int e;
};

int main() {
std::list<base> mylist;
child1 _c1;
child2 _c2;
mylist.push_back(_c1);
mylist.push_back(_c2);
return 0;
}

It seems that I lose the information of _c1 and _c2 like they are
converted to base.

Please, do you have any idea how can I achieve that? Do I have to
implement my own container?

Many thanks in advance,
-- George

 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      02-16-2007
George Exarchakos wrote:
>
>
> Can we have a std::list<BASE> where BASE be the base class of a class
> hierarchy? I want to add to this list objects that are inherited from
> BASE class but not necessarily the same...
>
> [redacted]
>
> Please, do you have any idea how can I achieve that? Do I have to
> implement my own container?


You've run into the slicing problem. You need to create a container of
(smart) pointers to your base class.

That is, std::list<base*>, or std::list<some_smart_ptr<base> >

See the FAQ, http://www.parashift.com/c++-faq-lit....html#faq-34.4




 
Reply With Quote
 
 
 
 
George Exarchakos
Guest
Posts: n/a
 
      02-16-2007
On Feb 16, 5:51 pm, red floyd <(E-Mail Removed)> wrote:
> George Exarchakos wrote:
>
> > Can we have a std::list<BASE> where BASE be the base class of a class
> > hierarchy? I want to add to this list objects that are inherited from
> > BASE class but not necessarily the same...

>
> > [redacted]
> >

>
> > Please, do you have any idea how can I achieve that? Do I have to
> > implement my own container?

>
> You've run into the slicing problem. You need to create a container of
> (smart) pointers to your base class.
>
> That is, std::list<base*>, or std::list<some_smart_ptr<base> >
>
> See the FAQ,http://www.parashift.com/c++-faq-lit....html#faq-34.4


Many thanks Red Floyd! This tip is exactly what I was looking for...
-- George

 
Reply With Quote
 
Roland Pibinger
Guest
Posts: n/a
 
      02-16-2007
On 16 Feb 2007 09:17:51 -0800, "George Exarchakos" wrote:
>Can we have a std::list<BASE> where BASE be the base class of a class
>hierarchy? I want to add to this list objects that are inherited from
>BASE class but not necessarily the same...


STL does not support object-oriented programming. STL containers,
iterators and algorithms are designed only for values, not for
(pointers to) objects. Workarounds exist but with 'Standard' STL there
always remains an 'impedance mismatch' when objects are used.

Best regards,
Roland Pibinger
 
Reply With Quote
 
paul.joseph.davis@gmail.com
Guest
Posts: n/a
 
      02-17-2007
On Feb 16, 1:05 pm, (E-Mail Removed) (Roland Pibinger) wrote:
> On 16 Feb 2007 09:17:51 -0800, "George Exarchakos" wrote:
>
> >Can we have a std::list<BASE> where BASE be the base class of a class
> >hierarchy? I want to add to this list objects that are inherited from
> >BASE class but not necessarily the same...

>
> STL does not support object-oriented programming.


I think that this comment is misleading. If I understand the point of
the statement, its that using objects that use polymorphism in a
container isn't supported. Because this isn't the case at all.
Although, objects used with the STL must provide certain concepts,
such as default constructibility, copy constructibility et al.

When dealing with class hierarchies, we must pay special attention to
copy constructibility and other concepts because these can lead to
problems such as slicing as noticed by the OP.

Using pointers is a perfectly valid method of fixing this issue.

On the other hand, if Roland meant that "You can't subclass objects
such as std::vector." then he is in fact correct. IIRC, most stl
objects don't provide a virtual destructor. And further, the STL (as
its name suggests) is a library of templates. Using templates with
inheritance is at best tricky.

I'm not sure what the actual standard has to say on this, but g++
4.0.2 won't compile this:

class A
{
public:
A() {}
~A() {}

template< typename TYPE >
virtual void
echo( TYPE val ) = 0 ;
} ;

The error is:
error: invalid use of 'virtual' in template declaration of 'virtual
void A::echo(TYPE)'

This all makes sense if we think in terms of the (non-standard
dictated) vtable implementation of polymorphism. When we create the
vtable for A, we have no idea how many entries it will have.
Theoretically, it would need to have an entry for every template
instantiation of A::echo(TYPE).

Whats more, this class definition could possibly change after it has
been compiled. Ie, compiled in a library, then some client code calls
A::echo(TYPE) with a type thats not used in the library. Thus the
vtable would change and break all sorts of things.

STL containers,
> iterators and algorithms are designed only for values, not for
> (pointers to) objects.


This is just wrong. A pointer *is* a value. Its a memory address. STL
containers will work just fine with pointers.

Objects on the other hand must provide the required concepts as
mentioned before. The entire point of the STL is to provide a system
that allows for use with any custom type. They'd be pretty pointless
if they could only hold things like int, float, char* et al.

Workarounds exist but with 'Standard' STL there
> always remains an 'impedance mismatch' when objects are used.
>


I'm not entirely certain what 'impedance mismatch' means. Although it
kinda reminds me of studying power amplifiers...

But the point that needs to be made here is that using smart pointers
in a container is not a work around. Smart pointers are a means to
perform resource control. In the case of using pointers, if the only
copy of a pointer to an object is in a std::vector, and then
std::vector::clear() is called, then the objects in it are leaked
(assuming we don't have copies to the pointer anywhere else). Smart
pointers do reference counting ( or some other method ) to determine
when an object should be delete'ed. So when std::vector::clear() is
called, the smart pointers can determine whether or not the object
should be delete'ed and thuse, no memory is leaked.

> Best regards,
> Roland Pibinger


HTH,
Paul Davis

 
Reply With Quote
 
Gavin Deane
Guest
Posts: n/a
 
      02-17-2007
On 17 Feb, 01:29, "(E-Mail Removed)"
<(E-Mail Removed)> wrote:
> On the other hand, if Roland meant that "You can't subclass objects
> such as std::vector." then he is in fact correct. IIRC, most stl
> objects don't provide a virtual destructor.


That doesn't stop me deriving from them.
#include <vector>
class foo : public std::vector<int> {};

Nothing wrong there. The only thing I can't do without a virtual
destructor is delete polymorphically.

Whether deriving from standard containers is a good idea or not is a
different question, but there is certainly nothing that prevents it.

Gavin Deane

 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-17-2007
Gavin Deane wrote:

> On 17 Feb, 01:29, "(E-Mail Removed)"
> <(E-Mail Removed)> wrote:
>> On the other hand, if Roland meant that "You can't subclass objects
>> such as std::vector." then he is in fact correct. IIRC, most stl
>> objects don't provide a virtual destructor.

>
> That doesn't stop me deriving from them.
> #include <vector>
> class foo : public std::vector<int> {};
>
> Nothing wrong there. The only thing I can't do without a virtual
> destructor is delete polymorphically.
>
> Whether deriving from standard containers is a good idea or not is a
> different question, but there is certainly nothing that prevents it.


Except that, formally, an implementation of std::vector<> that prevents
derivation (using a virtual base class trick getting) is standard
compliant. In practice, all implementations of the standard library allow
for derivation; and I do not hesitate to derive from standard container
classes whenever it feels appropriate. However, I do not see any blessing
for this technique in the standard. As far as I can tell, this would be a
compliant implementation:

namespace std {

class __protected_constructor {
protected:

__protected_constructor ( void ) {}

}; // protected_constructor

template < typename T, typename A >
class vector : private virtual __protected_constructor {

// ... do the vector business.

}; // vector

}


Best

Kai-Uwe Bux
 
Reply With Quote
 
Roland Pibinger
Guest
Posts: n/a
 
      02-17-2007
On 16 Feb 2007 17:29:09 -0800, paul joseph wrote:
>On Feb 16, 1:05 pm, (E-Mail Removed) (Roland Pibinger) wrote:
>> STL does not support object-oriented programming.

>
>I think that this comment is misleading. If I understand the point of
>the statement, its that using objects that use polymorphism in a
>container isn't supported.


Just look at the containers, iterators and algorithms. No algorithm
works with (pointers to) objects (except random_shuffle).

>Because this isn't the case at all.
>Although, objects used with the STL must provide certain concepts,
>such as default constructibility, copy constructibility et al.
>When dealing with class hierarchies, we must pay special attention to
>copy constructibility and other concepts because these can lead to
>problems such as slicing as noticed by the OP.


Objects (in the meaning used in object-oriented programing) are
characterized by identity, state and behavior. It makes no sense to
copy or assign objects. Copy constructibility makes only sense for
values and value-oriented libraries like STL.

>Using pointers is a perfectly valid method of fixing this issue.


If it needs fixing it must be broken.

>STL containers,
>> iterators and algorithms are designed only for values, not for
>> (pointers to) objects.

>
>This is just wrong. A pointer *is* a value. Its a memory address. STL
>containers will work just fine with pointers.


A pointer is not a value, otherwise one could just use an int instead.
A pointer in C/C++ has the combined meaning of reference and address.

>Objects on the other hand must provide the required concepts as
>mentioned before.


The 'required concepts' make sense only for values, not objects.

>The entire point of the STL is to provide a system
>that allows for use with any custom type. They'd be pretty pointless
>if they could only hold things like int, float, char* et al.


.... and 'concrete types' as Stroustrup calls them.

>Workarounds exist but with 'Standard' STL there
>> always remains an 'impedance mismatch' when objects are used.

>
>I'm not entirely certain what 'impedance mismatch' means. Although it
>kinda reminds me of studying power amplifiers...


It means the mismatch that becomes evident when you try to use objects
with the value-based STL library.

>But the point that needs to be made here is that using smart pointers
>in a container is not a work around. Smart pointers are a means to
>perform resource control.


Since 'smart pointers' only try to imitate real pointers the
'impedance mismatch' is the same.

In general, STL is the attempt introduce the functional paradigm into
the C++ language as counterpart to the object-oriented paradigm. This
attempt has produced much misunderstanding and confusion.

Best wishes,
Roland Pibinger
 
Reply With Quote
 
Alf P. Steinbach
Guest
Posts: n/a
 
      02-17-2007
* Kai-Uwe Bux:
>
> ... formally, an implementation of std::vector<> that prevents
> derivation (using a virtual base class trick getting) is standard
> compliant.


Sorry, that's incorrect.

17.3.1.2/1 "The library can be extended by a C++ program. ... Such
extensions are generally one of the following: ... Derived classes."

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
 
Reply With Quote
 
paul.joseph.davis@gmail.com
Guest
Posts: n/a
 
      02-17-2007
On Feb 17, 1:12 pm, (E-Mail Removed) (Roland Pibinger) wrote:
> On 16 Feb 2007 17:29:09 -0800, paul joseph wrote:
>
> >On Feb 16, 1:05 pm, (E-Mail Removed) (Roland Pibinger) wrote:
> >> STL does not support object-oriented programming.

>
> >I think that this comment is misleading. If I understand the point of
> >the statement, its that using objects that use polymorphism in a
> >container isn't supported.

>
> Just look at the containers, iterators and algorithms. No algorithm
> works with (pointers to) objects (except random_shuffle).
>


This examples shows how to use std::sort on a std::vector or pointers.
As well as a trivial example of std::for_each to print the vector.

#include <iostream>
#include <vector>

class A
{
public:
A( int val )
{
_val = val ;
}

~A() {}

int
value()
{
return _val ;
}

private:

int _val ;
} ;

bool
compare( A* lhs, A* rhs )
{
return lhs->value() < rhs->value() ;
}

void
echo( A* a )
{
std::cout << a->value() << std::endl ;
}

int
main( int argc, char* argv[] )
{
std::vector< A* > vec ;

for( int i = 10 ; i > 0 ; i-- )
{
A* a = new A( i ) ;
vec.push_back( a ) ;
}

std::cout << "Before sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;

std::sort( vec.begin(), vec.end(), compare ) ;

std::cout << "After sort:" << std::endl ;
std::for_each( vec.begin(), vec.end(), echo ) ;
}

> >Because this isn't the case at all.
> >Although, objects used with the STL must provide certain concepts,
> >such as default constructibility, copy constructibility et al.
> >When dealing with class hierarchies, we must pay special attention to
> >copy constructibility and other concepts because these can lead to
> >problems such as slicing as noticed by the OP.

>
> Objects (in the meaning used in object-oriented programing) are
> characterized by identity, state and behavior. It makes no sense to
> copy or assign objects. Copy constructibility makes only sense for
> values and value-oriented libraries like STL.
>


You're right, wrong, and neither right or wrong. Of course objects are
characterized by their state and behavior. You're absolutely wrong
that it makes no sense to copy or assign objects, there are instances
where this may be true, but its just plain wrong to say never. I use
it quite a bit.

And the last bit that copy constructibility only makes sense in the
STL isn't quite right, although I don't tend to use it alot in my own
code, thats mostly becuase I don't write code that requires this
concept.

> >Using pointers is a perfectly valid method of fixing this issue.

>
> If it needs fixing it must be broken.
>
> >STL containers,
> >> iterators and algorithms are designed only for values, not for
> >> (pointers to) objects.

>
> >This is just wrong. A pointer *is* a value. Its a memory address. STL
> >containers will work just fine with pointers.

>
> A pointer is not a value, otherwise one could just use an int instead.
> A pointer in C/C++ has the combined meaning of reference and address.
>


You can use an int for a pointer! (Disclaimer: Its very ill advised,
bad C++, and requires that an int be the same size as the pointer you
wish to obfuscate.)

> >Objects on the other hand must provide the required concepts as
> >mentioned before.

>
> The 'required concepts' make sense only for values, not objects.
>
> >The entire point of the STL is to provide a system
> >that allows for use with any custom type. They'd be pretty pointless
> >if they could only hold things like int, float, char* et al.

>
> ... and 'concrete types' as Stroustrup calls them.
>
> >Workarounds exist but with 'Standard' STL there
> >> always remains an 'impedance mismatch' when objects are used.

>
> >I'm not entirely certain what 'impedance mismatch' means. Although it
> >kinda reminds me of studying power amplifiers...

>
> It means the mismatch that becomes evident when you try to use objects
> with the value-based STL library.
>
> >But the point that needs to be made here is that using smart pointers
> >in a container is not a work around. Smart pointers are a means to
> >perform resource control.

>
> Since 'smart pointers' only try to imitate real pointers the
> 'impedance mismatch' is the same.
>


I'm unsure as to how I should respond to this.

Yes, smart pointers only imitate real pointers. They are actually
objects that use a little voodoo to track the resources they own (The
underlying raw pointer). Because they are objects, they can be copied
and assigned. Writing code without smart pointers is ill-advised in my
opinion.

The only 'mismatch' that occurs with the objects used in the STL is
when the object doesn't support something required of it. The
algorithms in the STL were designed to work with any user defined type
as long as those types support a few basic operations. Obviously, if
something doesn't meet these requirements it won't work. You'll find
this happens alot when requirements aren't met.

> In general, STL is the attempt introduce the functional paradigm into
> the C++ language as counterpart to the object-oriented paradigm. This
> attempt has produced much misunderstanding and confusion.
>


Obviously the STL can be misunderstood...

> Best wishes,
> Roland Pibinger



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Are sequence containers not a subset of general containers? Sebastian Mach C++ 5 10-06-2012 07:54 PM
Proper use of templated containers as class members Per C++ 10 12-08-2008 09:46 AM
Containers of iterators vs. containers of references clark.coleman@att.net C++ 7 01-25-2008 01:37 PM
Subtypes of templated types (in templated functions) Marijn C++ 5 02-13-2004 09:50 AM
implementing a templated struct within a templated struct RA Scheltema C++ 3 01-06-2004 11:25 AM



Advertisments