By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,610 Members | 1,989 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,610 IT Pros & Developers. It's quick & easy.

Deriving a regular class from a template?

P: n/a
This may be another question having an obvious answer, but I'm not seeing
it. I'm trying to create a class that derives from
std::valarray<std::string>. I don't need a template, and I haven't come
across any examples of a construct like what I show below. Perhapes it's
simply a bad idea. If there is something fundamentally wrong with this
approach please let me know.

Can anybody tell me if there is a way to get the following to work? I can
get the class StringArray to compile, but it fails to link correctly:

#include <valarray>
#include <string>

namespace stringer{
using std::valarray;
using std::string;

class StringArray:public valarray<string> {
public:
StringArray(const size_t& vsize):valarray<string>(vsize){}
};

StringArray stringV(3); // this is what seems to be failing
}

This is the point where it fails:

g++ -o stringer main.o -L/usr/lib/ -L/usr/lib/qt3/lib/ -L/usr/X11R6/lib/
-lqt -lXext -lX11 -lm
main.o(.text+0xd7): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x155): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x196): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `__gnu_cxx::__exchange_and_add(int volatile*, int)'

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
Jul 22 '05 #1
Share this Question
Share on Google+
28 Replies


P: n/a

"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message
news:u5********************@speakeasy.net...
This may be another question having an obvious answer, but I'm not seeing
it. I'm trying to create a class that derives from
std::valarray<std::string>. I don't need a template, and I haven't come
across any examples of a construct like what I show below. Perhapes it's
simply a bad idea. If there is something fundamentally wrong with this
approach please let me know.

Can anybody tell me if there is a way to get the following to work? I can
get the class StringArray to compile, but it fails to link correctly:

#include <valarray>
#include <string>

namespace stringer{
using std::valarray;
using std::string;

class StringArray:public valarray<string> {
public:
StringArray(const size_t& vsize):valarray<string>(vsize){}
};

StringArray stringV(3); // this is what seems to be failing
}

This is the point where it fails:

g++ -o stringer main.o -L/usr/lib/ -L/usr/lib/qt3/lib/ -L/usr/X11R6/lib/ -lqt -lXext -lX11 -lm
main.o(.text+0xd7): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x155): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x196): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `__gnu_cxx::__exchange_and_add(int volatile*, int)'


Your code compiles and links for me. I can't see anything illegal about it.

OTOH I'm not sure its a good idea.

Firstly from the code you posted

typedef std::valarray<std::string> StringArray;

seems a simpler option, but maybe you have reasons for doing this that
aren't in the posted code.

Secondly valarray is really designed for numeric types, I don't think using
it with strings is illegal but its a bit odd, why not
std::vector<std::string>?

Thirdly deriving from standard container classes is frowned upon because
they lack a virtual destructor. Something like this is safer and may be
closer to your needs

class StringArray
{
public:
...
private:
std::valarray<std::string> data;
};

john
Jul 22 '05 #2

P: n/a
John Harrison wrote:
Your code compiles and links for me. I can't see anything illegal about
it.
Indeed. I just built and installed gcc (GCC) 3.4.0. I had been using qmake
to create the Makefile. That's would have worked if my setup were
standard. But it was trying to link against a different set of libs. In
particular the -L/usr/lib. I thought gcc would take precedence over that,
until I looked it up. Oh, and then there's the aclocal-1.8 that came with
automake, and didn't get the proper symlink from the `make install'! It
goes on and on... :-/
OTOH I'm not sure its a good idea.

Firstly from the code you posted

typedef std::valarray<std::string> StringArray;

seems a simpler option, but maybe you have reasons for doing this that
aren't in the posted code.
My initial motivation was to set the values of the valarray in an
initialization function, hence the desire for a derived class.
Secondly valarray is really designed for numeric types, I don't think
using it with strings is illegal but its a bit odd, why not
std::vector<std::string>?
I'm using the strings so I can mark the individual elements while I play
around with different slicing, indexing and etc. It's just a learning toy.
Thirdly deriving from standard container classes is frowned upon because
they lack a virtual destructor.
That's good to know. I'm now wondering if I can explicitly call the
destructor on the baseclass. Hmmmm....
Something like this is safer and may be
closer to your needs

class StringArray
{
public:
...
private:
std::valarray<std::string> data;
};


That crossed my mind. In this case, it's probably better to do the has-a
rather than an is-a. Thanks for the help. The verification that it
compiled was valuable information.

--
STH
Hatton's Law: "There is only One inviolable Law"
KDevelop: http://www.kdevelop.org SuSE: http://www.suse.com
Mozilla: http://www.mozilla.org
Jul 22 '05 #3

P: n/a
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<u5********************@speakeasy.net>...
This may be another question having an obvious answer, but I'm not seeing
it. I'm trying to create a class that derives from
std::valarray<std::string>. I don't need a template, and I haven't come
across any examples of a construct like what I show below. Perhapes it's
simply a bad idea. If there is something fundamentally wrong with this
approach please let me know.

Can anybody tell me if there is a way to get the following to work? I can
get the class StringArray to compile, but it fails to link correctly:

#include <valarray>
#include <string>

namespace stringer{
using std::valarray;
using std::string;

class StringArray:public valarray<string> {
public:
StringArray(const size_t& vsize):valarray<string>(vsize){}
};

StringArray stringV(3); // this is what seems to be failing
}

This is the point where it fails:

g++ -o stringer main.o -L/usr/lib/ -L/usr/lib/qt3/lib/ -L/usr/X11R6/lib/
-lqt -lXext -lX11 -lm
main.o(.text+0xd7): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>, : undefined reference to `__gnu_cxx::__exchange_and_add(int volatile*, int> std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x155): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x196): In function `__static_initialization_and_destruction_
(int, int)':)'


One possibility is that, since the std::valarray container is really
for optimized numerical calculations, it has some special restrictions
which cause problems if you try to initialize a valarray with a
non-numerical type (c.f. sec 26.3 of the standard). I would suggest
using std::vector<std::string> .. that should definitely work .. I
have used it myself in the past.

HTH, Dave Moore
Jul 22 '05 #4

P: n/a
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<u5********************@speakeasy.net>...
Can anybody tell me if there is a way to get the following to work? I can
get the class StringArray to compile, but it fails to link correctly:

#include <valarray>
#include <string>

namespace stringer{
using std::valarray;
using std::string;

class StringArray:public valarray<string> {
public:
StringArray(const size_t& vsize):valarray<string>(vsize){}
};

StringArray stringV(3); // this is what seems to be failing
}


Should work, and in fact works when compiled with VC7.1. It seems
you should ask in the group for your compiler.

Regards,
Michiel Salters
Jul 22 '05 #5

P: n/a
"Steven T. Hatton" <su******@setidava.kushan.aa> wrote in message news:<u5********************@speakeasy.net>...
This may be another question having an obvious answer, but I'm not seeing
it. I'm trying to create a class that derives from
std::valarray<std::string>.
This is a bad idea, for at least three reasons:

i) valarray is a special container designed for numerical applications,
so there is propbably no point in using it with string

ii) IIRC there are some restrictions in the standard for using valarray,
to the consequence that using it with string yields undefined
behaviour

iii) deriving from classes which are not designed as base classes, like
the standard library containers, is considered bad practice in C++,
e.g. the lack of a virtual destructor may prove fatal

To your more general question if one can derive a concrete class from
a template instantiation: Yes, that's possible.

If you had used vector instead of valarray, your example would be correct,
even if bad style, for reason iii).

And if you look at your error message, you might see that the code as written
compiled fine. The error message refers to a linker error. You are probable
not linking against the C++ runtime library, or maybe you are linking against
a wrong one.

To solve this problem, check your documentation or ask in a newsgroup topical
to your compiler system.
I don't need a template, and I haven't come
across any examples of a construct like what I show below. Perhapes it's
simply a bad idea. If there is something fundamentally wrong with this
approach please let me know.

Can anybody tell me if there is a way to get the following to work? I can
get the class StringArray to compile, but it fails to link correctly:

#include <valarray>
#include <string>

namespace stringer{
using std::valarray;
using std::string;

class StringArray:public valarray<string> {
public:
StringArray(const size_t& vsize):valarray<string>(vsize){}
};

StringArray stringV(3); // this is what seems to be failing
}

This is the point where it fails:

g++ -o stringer main.o -L/usr/lib/ -L/usr/lib/qt3/lib/ -L/usr/X11R6/lib/
-lqt -lXext -lX11 -lm
main.o(.text+0xd7): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x155): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `std::basic_string<char, std::char_traits<char>,
std::allocator<char> >::_Rep::_S_empty_rep_storage'
main.o(.text+0x196): In function `__static_initialization_and_destruction_
(int, int)':
: undefined reference to `__gnu_cxx::__exchange_and_add(int volatile*, int)'

Jul 22 '05 #6

P: n/a
>
Thirdly deriving from standard container classes is frowned upon because
they lack a virtual destructor.


That's good to know. I'm now wondering if I can explicitly call the
destructor on the baseclass. Hmmmm....


There's no need to do that. The problem is with code like the following

valarray<string>* p = new StringArray(10);
delete p;

That is undefined behaviour. Deleting a derived class object through a
pointer to a base class when that base class lacks a virtual destructor
results in undefined behaviour. The issue for you is how likely it is that
code like the above will be written with your StringArray class.

john
Jul 22 '05 #7

P: n/a
sc********************@sigma-c.com (Uwe Schnitker) wrote in message news:<30**************************@posting.google. com>...
iii) deriving from classes which are not designed as base classes, like
the standard library containers, is considered bad practice in C++,
e.g. the lack of a virtual destructor may prove fatal


This idea is new to me .. do you have a reference where I can read
about it in more detail? In the past I have routinely derived classes
from std::vector and std::valarray, usually publicly, but sometimes
privately. I have done this when it seemed natural to do so in terms
of the "is-a" formalism for building class hierarchies. For example,

class positionArray : public std::vector<double> {
// some private data that is needed for manipulating the elements
// of the array
public:
positionArray(int size) : std::vector<double>(size) {
// whatever
}

void permute(); //
};
In my application positionArray is conceptually a vector of double, so
it makes sense to apply operations like subscripting directly, rather
than through an access function referencing a std::vector<double>
member. The positionArray class then would then typically also have a
few member functions for carrying out particular operations on the
underlying std::vector<double>.

I rarely use virtual functions or multiple inheritance, so the lack of
a virtual destructor has never been a problem for me .. although I
certainly see your point about that being a potential problem in the
more general case. Are there other weaknesses associated with
deriving from STL containers? If there are none, then it seems like
your advice above is perhaps a bit too restrictive.

Just my $0.02 ... Dave Moore
Jul 22 '05 #8

P: n/a
"Dave Moore" <dt*****@rijnh.nl> wrote...
sc********************@sigma-c.com (Uwe Schnitker) wrote in message news:<30**************************@posting.google. com>...
iii) deriving from classes which are not designed as base classes, like the standard library containers, is considered bad practice in C++, e.g. the lack of a virtual destructor may prove fatal

[...] Are there other weaknesses associated with
deriving from STL containers? If there are none, then it seems like
your advice above is perhaps a bit too restrictive.


No other weaknesses. The advice is usually directed at newbies so
that they don't get into a habit of deriving whenever they need to.

A note: I often find it helpful to derive privately. Then I can
control what functionality is exposed and I definitely prevent such
blunders as accidental polymorphic deletion.

Victor
Jul 22 '05 #9

P: n/a
Victor Bazarov wrote:

"Dave Moore" <dt*****@rijnh.nl> wrote...
sc********************@sigma-c.com (Uwe Schnitker) wrote in message

news:<30**************************@posting.google. com>...
iii) deriving from classes which are not designed as base classes, like the standard library containers, is considered bad practice in C++, e.g. the lack of a virtual destructor may prove fatal

[...] Are there other weaknesses associated with
deriving from STL containers? If there are none, then it seems like
your advice above is perhaps a bit too restrictive.


No other weaknesses. The advice is usually directed at newbies so
that they don't get into a habit of deriving whenever they need to.

A note: I often find it helpful to derive privately. Then I can
control what functionality is exposed and I definitely prevent such
blunders as accidental polymorphic deletion.

Victor


So, if that is the case, then deriving from std containers should *NOT* be
labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.

I'm sure that _misnaming_ something 'bad practice/design' causes a lot more
problems that it is intended to solve.
Jul 22 '05 #10

P: n/a
"Julie" <ju***@nospam.com> wrote
Victor Bazarov wrote:
A note: I often find it helpful to derive privately. Then I can
control what functionality is exposed and I definitely prevent such
blunders as accidental polymorphic deletion.

Victor
So, if that is the case, then deriving from std containers should *NOT* be
labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.


There's nothing advanced about the technique. It's simply error-prone, and so
should be avoided by anyone who doesn't understand the pitfalls and
limitations.
I'm sure that _misnaming_ something 'bad practice/design' causes a lot more
problems that it is intended to solve.


It is a bad practice. The mitigating factor is that an expert will be able to
make bad practices work and will know how to limit the scope. Obviously, anyone
who has worked with a tool for a substantial amount of time will know how to
use otherwise inappropriate shortcuts to good effect, but that's an attribute
of the practitioner, not of the technique. I would certainly be more confident
of something unorthodox from Victor than I would from a completely orthodox
implementation from newbie-come-lately. That doesn't change that the practice
is frowned upon in a larger context. It's not because Evel Knievel can
successfully and reproducibly jump a motorcycle over a row of buses that
suddenly it becomes an acceptable practice for all bikers. It's an acceptable
practice for Evel Knievel.

Claudio Puviani
Jul 22 '05 #11

P: n/a
Claudio Puviani wrote:

"Julie" <ju***@nospam.com> wrote
Victor Bazarov wrote:
A note: I often find it helpful to derive privately. Then I can
control what functionality is exposed and I definitely prevent such
blunders as accidental polymorphic deletion.

Victor


So, if that is the case, then deriving from std containers should *NOT* be
labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.


There's nothing advanced about the technique. It's simply error-prone, and so
should be avoided by anyone who doesn't understand the pitfalls and
limitations.


The "pitfalls" are:

1. the behavior is undefined if you delete an object of a derived type
through a pointer to the base type.

The "limitations" are:

1. don't do that.

Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad. Programming is a profession. If you can't pay
enough attention to do it right, don't do it at all.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #12

P: n/a
"Pete Becker" <pe********@acm.org> wrote
Claudio Puviani wrote:

"Julie" <ju***@nospam.com> wrote
Victor Bazarov wrote:
> A note: I often find it helpful to derive privately. Then I can
> control what functionality is exposed and I definitely prevent such
> blunders as accidental polymorphic deletion.
>
> Victor

So, if that is the case, then deriving from std containers should *NOT* be labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.
There's nothing advanced about the technique. It's simply error-prone, and so should be avoided by anyone who doesn't understand the pitfalls and
limitations.


The "pitfalls" are:

1. the behavior is undefined if you delete an object of a derived type
through a pointer to the base type.


I wasn't aware that a pointer to the base class could point to a class that
privately inherits from the base.

The "limitations" are:

1. don't do that.

Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad.
You'll notice in the rest of my post -- which you snipped -- that I refer to
the technique as a short-cut, not as a design choice. The whole point, which I
don't believe was at all obscure, was that as a rule, it's a bad practice. In
fact, I don't hint at it; I explicitly say, "It is a bad practice."
Programming is a profession. If you can't pay enough attention
to do it right, don't do it at all.


I certainly hope this last part wasn't directed at me. You've been on this
newsgroup long enough that you've seen me bash many times the idea of
inheriting from classes that aren't designed for it. If I can homorously parody
the lecturing tone of the two last sentences: people who jump the gun shouldn't
own guns.

Claudio Puviani
Jul 22 '05 #13

P: n/a
Claudio Puviani wrote:
Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad.
You'll notice in the rest of my post -- which you snipped -- that I refer to
the technique as a short-cut, not as a design choice.


Sorry, I didn't mean to be as harsh as that sounded.
The whole point, which I
don't believe was at all obscure, was that as a rule, it's a bad practice. In
fact, I don't hint at it; I explicitly say, "It is a bad practice."


Yup, and I explicitly disagreed with that.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #14

P: n/a
"Pete Becker" <pe********@acm.org> wrote
Claudio Puviani wrote:
Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad.


You'll notice in the rest of my post -- which you snipped -- that I refer to the technique as a short-cut, not as a design choice.


Sorry, I didn't mean to be as harsh as that sounded.


No problem. I'm hardly a diplomat myself. :-)
The whole point, which I don't believe was at all obscure, was
that as a rule, it's a bad practice. In fact, I don't hint at it; I
explicitly say, "It is a bad practice."


Yup, and I explicitly disagreed with that.


I'm confused now. When you said, "1. don't do that," I was under the impression
that you were agreeing with me. Are you saying that inheriting from inheriting
from standard containers is a good practice? If you are -- and we'd definitely
be in disagreement -- what did you mean by "don't do that"?

Claudio Puviani
Jul 22 '05 #15

P: n/a
Claudio Puviani wrote:

I'm confused now. When you said, "1. don't do that," I was under the impression
that you were agreeing with me. Are you saying that inheriting from inheriting
from standard containers is a good practice? If you are -- and we'd definitely
be in disagreement -- what did you mean by "don't do that"?

I mean what I said:
The "pitfalls" are:

1. the behavior is undefined IF YOU DELETE AN OBJECT OF A DERIVED TYPE
THROUGH A POINTER TO THE BASE TYPE.

The "limitations" are:

1. don't do that.


There are no nasty surprises here, certainly nothing to justify your
comparison to Evel Knievel.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #16

P: n/a
"Pete Becker" <pe********@acm.org> wrote
Claudio Puviani wrote:

I'm confused now. When you said, "1. don't do that," I was under the impression that you were agreeing with me. Are you saying that inheriting from inheriting from standard containers is a good practice? If you are -- and we'd definitely be in disagreement -- what did you mean by "don't do that"?

I mean what I said:
The "pitfalls" are:

1. the behavior is undefined IF YOU DELETE AN OBJECT OF A DERIVED TYPE
THROUGH A POINTER TO THE BASE TYPE.

The "limitations" are:

1. don't do that.


Unfortunately, using pronouns tends to be ambiguous. The "that" in "don't do
that" could just as easily refered to inheriting from a non-polymorphic type. I
follow what you were saying now that "that" is bound to the preceding
statement. :-)
There are no nasty surprises here, certainly nothing to justify your
comparison to Evel Knievel.


With private inheritance, I agree (and the "deleting through a pointer to the
base" admonition is also unnecessary since it can't be done). I wholeheartedly
stand by my comparison with respect to public inheritance from a
non-polymorphic type, however.

Claudio Puviani
Jul 22 '05 #17

P: n/a
Claudio Puviani wrote:

"Pete Becker" <pe********@acm.org> wrote
There are no nasty surprises here, certainly nothing to justify your
comparison to Evel Knievel.
With private inheritance, I agree (and the "deleting through a pointer to the
base" admonition is also unnecessary since it can't be done).


It can be done. Think a little harder.
I wholeheartedly
stand by my comparison with respect to public inheritance from a
non-polymorphic type, however.


You need to cite facts; restating your opinion doesn't add any
information. What nasty surprises do you think are here that make this
too hazardous for most programmers to use?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #18

P: n/a
"Pete Becker" <pe********@acm.org> wrote
Claudio Puviani wrote:

"Pete Becker" <pe********@acm.org> wrote
There are no nasty surprises here, certainly nothing to justify your
comparison to Evel Knievel.


I wholeheartedly stand by my comparison with respect to public
inheritance from a non-polymorphic type, however.


You need to cite facts; restating your opinion doesn't add any
information. What nasty surprises do you think are here that make this
too hazardous for most programmers to use?


I built up an argument, only to convince myself that you're right. Oh, there
were pitfalls all right (ex: changing the behavior in a non-virtual function
override), but they all also apply to inheritance from polymorphic types, so
it's inconsistent of me to single out non-polymorphic types for practices that
would be just as problematic elsewhere. In retrospect, those people I've seen
who had mangled projects by incorrectly inheriting from non-polymorphic types
weren't doing much better with the polymorphic types. In fact, they were doing
worse.

So consider my opinion retracted and my paranoia focused to a finer
grainularity.

Claudio Puviani
Jul 22 '05 #19

P: n/a
Claudio Puviani wrote:

So consider my opinion retracted and my paranoia focused to a finer
grainularity.


<g>

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #20

P: n/a
Claudio Puviani wrote:

"Julie" <ju***@nospam.com> wrote
Victor Bazarov wrote:
A note: I often find it helpful to derive privately. Then I can
control what functionality is exposed and I definitely prevent such
blunders as accidental polymorphic deletion.

Victor


So, if that is the case, then deriving from std containers should *NOT* be
labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.


There's nothing advanced about the technique. It's simply error-prone, and so
should be avoided by anyone who doesn't understand the pitfalls and
limitations.
I'm sure that _misnaming_ something 'bad practice/design' causes a lot more
problems that it is intended to solve.


It is a bad practice. The mitigating factor is that an expert will be able to
make bad practices work and will know how to limit the scope. Obviously, anyone
who has worked with a tool for a substantial amount of time will know how to
use otherwise inappropriate shortcuts to good effect, but that's an attribute
of the practitioner, not of the technique. I would certainly be more confident
of something unorthodox from Victor than I would from a completely orthodox
implementation from newbie-come-lately. That doesn't change that the practice
is frowned upon in a larger context. It's not because Evel Knievel can
successfully and reproducibly jump a motorcycle over a row of buses that
suddenly it becomes an acceptable practice for all bikers. It's an acceptable
practice for Evel Knievel.


I really don't get your point. At first, you say that it isn't an advanced
technique, then you go off to essentially say that it is acceptable for
experienced/expert users to use it???

Maybe you misinterpreted my intended meaning of advanced: intended to be used
by experienced programmers that recognize and understand the pitfalls and
limitations.
Jul 22 '05 #21

P: n/a
Pete Becker wrote:

Claudio Puviani wrote:

"Julie" <ju***@nospam.com> wrote
Victor Bazarov wrote:
> A note: I often find it helpful to derive privately. Then I can
> control what functionality is exposed and I definitely prevent such
> blunders as accidental polymorphic deletion.
>
> Victor

So, if that is the case, then deriving from std containers should *NOT* be
labeled as a bad practice (bad design, etc.), but rather as an 'advanced
construct or idiom'.


There's nothing advanced about the technique. It's simply error-prone, and so
should be avoided by anyone who doesn't understand the pitfalls and
limitations.


The "pitfalls" are:

1. the behavior is undefined if you delete an object of a derived type
through a pointer to the base type.

The "limitations" are:

1. don't do that.

Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad. Programming is a profession. If you can't pay
enough attention to do it right, don't do it at all.


Pete, no one is advocating not reading the documentation or not designing
code. However, I'd like to know where in the documentation (i.e. standard) it
says that standard containers should not be derived from.

Second: if the answer is an unconditional "don't do that", then why is it
possible? What is the cost of making the containers 'sealed' (so that they
_can't_ be derived from)? If the cost is low or nonexistent, why didn't the
committee make that the case?
Jul 22 '05 #22

P: n/a
Pete Becker wrote:
[snip]
Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad. Programming is a profession. If you can't pay
enough attention to do it right, don't do it at all.
I hope that you aren't *serious* about this statement... If you are, then I
really hope that you and the rest of the committee are making concerted efforts
to make sure that everything is completely and thoroughly documented so that
there is no misinterpretation in the usage of *ANY* language construct or
library element.
If you can't pay
enough attention to do it right, don't do it at all.


Pretty harsh words. Shall I go dig up all the corrections, retractions, etc.
from your column?
Jul 22 '05 #23

P: n/a
Julie wrote:

Pete Becker wrote:

Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad. Programming is a profession. If you can't pay
enough attention to do it right, don't do it at all.
Pete, no one is advocating not reading the documentation or not designing
code. However, I'd like to know where in the documentation (i.e. standard) it
says that standard containers should not be derived from.


It doesn't. This discussion was about the derived types, not the base
types. As I said, because the standard containers don't have virtual
destructors, if you delete a derived object through a pointer to the
base, the behavior of the code is undefined.

Second: if the answer is an unconditional "don't do that", then why is it
possible?
As with most undefined behavior, the reason is that it's too expensive
to check.
What is the cost of making the containers 'sealed' (so that they
_can't_ be derived from)? If the cost is low or nonexistent, why didn't the
committee make that the case?


There's little, if any, benefit from doing that, and there are
reasonable uses for it. What dangers do you see in deriving from
standard containers that would justify such a restriction?

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #24

P: n/a
Julie wrote:

Pete Becker wrote:
[snip]
Of course, if you don't read documentation or don't design your code
before you write it you may well run afoul of these "pitfalls and
limitations". Too bad. Programming is a profession. If you can't pay
enough attention to do it right, don't do it at all.


I hope that you aren't *serious* about this statement... If you are, then I
really hope that you and the rest of the committee are making concerted efforts
to make sure that everything is completely and thoroughly documented so that
there is no misinterpretation in the usage of *ANY* language construct or
library element.


That is, indeed, a large part of what writing a standard is about.

With regard to the point under discussion, the standard (5.3.5/3) is
quite clear: "In the first alternative (delete object), if the static
type of the operand is different from its dynamic type, the static type
shall be a base class of the operandís dynamic type and the static type
shall have a virtual destructor or the behavior is undefined."

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #25

P: n/a
Pete Becker wrote:
What is the cost of making the containers 'sealed' (so that they
_can't_ be derived from)? If the cost is low or nonexistent, why didn't the
committee make that the case?


There's little, if any, benefit from doing that, and there are
reasonable uses for it. What dangers do you see in deriving from
standard containers that would justify such a restriction?


I'm lost.

I thought that we were talking about deriving from std containers, your answer
was "don't do that", now it looks like you are saying "there are reasonable
uses for it".

Please clarify.
Jul 22 '05 #26

P: n/a
Julie wrote:

Pete Becker wrote:
What is the cost of making the containers 'sealed' (so that they
_can't_ be derived from)? If the cost is low or nonexistent, why didn't the
committee make that the case?


There's little, if any, benefit from doing that, and there are
reasonable uses for it. What dangers do you see in deriving from
standard containers that would justify such a restriction?


I'm lost.

I thought that we were talking about deriving from std containers, your answer
was "don't do that", now it looks like you are saying "there are reasonable
uses for it".

Please clarify.


I was talking about deleting derived objects through pointers to bases
without virtual destructors.

--

Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)
Jul 22 '05 #27

P: n/a
Pete Becker wrote:

Julie wrote:

Pete Becker wrote:
> What is the cost of making the containers 'sealed' (so that they
> _can't_ be derived from)? If the cost is low or nonexistent, why didn't the
> committee make that the case?

There's little, if any, benefit from doing that, and there are
reasonable uses for it. What dangers do you see in deriving from
standard containers that would justify such a restriction?


I'm lost.

I thought that we were talking about deriving from std containers, your answer
was "don't do that", now it looks like you are saying "there are reasonable
uses for it".

Please clarify.


I was talking about deleting derived objects through pointers to bases
without virtual destructors.


Ok, that is understood.

Now, what are your feelings about deriving from std containers? A 'bad thing'
or 'advanced* technique'?

(*Advanced meaning for programmers that fully understand the ramifications of
such)
Jul 22 '05 #28

P: n/a
In message <40**************@nospam.com>, Julie <ju***@nospam.com>
writes
Pete Becker wrote:
> What is the cost of making the containers 'sealed' (so that they
> _can't_ be derived from)? If the cost is low or nonexistent, why
>didn't the
> committee make that the case?


There's little, if any, benefit from doing that, and there are
reasonable uses for it. What dangers do you see in deriving from
standard containers that would justify such a restriction?


I'm lost.

I thought that we were talking about deriving from std containers, your answer
was "don't do that", now it looks like you are saying "there are reasonable
uses for it".

Please clarify.


FWIW I got the impression that PB's use of "don't do that" was not a
recommendation for how to code, but the "limitation" that should
therefore appear in the documentation - i.e. not "don't derive from
std:: containers" but "don't delete the result through base pointers".
The "pitfall" -- sliced deletion -- is countered by the "limitation" --
documentation forbids such deletion.

But maybe I'm more confused than the rest of you ;-(

--
Richard Herring
Jul 22 '05 #29

This discussion thread is closed

Replies have been disabled for this discussion.