Inheriting from STL bitset

S

shaun roe

Its the weekend so I have time to wax lyrical.
Thanks for the many answers and the discussion. I understand it is
generally dangerous to inherit from containers in STL, and not
inheriting in this way is a good general philosophy. Which is a shame,
since a technical detail of the language prevents preserving the idiom
embedded in much of STL and extending these well written, optimized,
classes in a natural way. But thats life.
However with a little more knowledge of the implicit problems, I think
it should be possible to weigh up the relevant dangers and be more
flexible: Given that bitset<> has method to_ulong, what could be more
natural than to have to_ulonglong (see ps at end) and maintain the idiom?

What is the probability in my application of the extended bitset being
called, destroyed polymorphically from a pointer to bitset<64>?
Infinitesimally small. Does my whimsical wish to preserve the style of
bitset outweigh this danger? In this case, probably.

So I'll commit my code to the project with a big doxygen warning and see
whether my evil misformed progeny trips anyone up...

thanks

shaun


ps: yes, I know standard C++ doesnt have an unsigned long long. This
wasn't my design choice. But its there, I have to live with it, and who
knows, maybe one day it will be part of the standard. "'to author' a
piece of code" (as opposed to "to write...") used to be an appalling
slaughter of the english language, but has become standard; and I'm told
that one can even find 'bodilicious' in the Oxford English Dictionary.
 
V

Victor Bazarov

shaun roe said:
Its the weekend so I have time to wax lyrical.
Thanks for the many answers and the discussion. I understand it is
generally dangerous to inherit from containers in STL, and not
inheriting in this way is a good general philosophy.

It is very disappointing that you understood one person's fears as
"general philosophy".
Which is a shame,
Indeed.

[...]
 
I

Ivan Vecerina

Victor Bazarov said:
It is very disappointing that you understood one person's fears as
"general philosophy".

One person's fears ? I think that the philosophy I have expressed
is supported my more than just one anonymous C++ user:
Herb Sutter: http://www.gotw.ca/publications/mill18.htm
Scott Meyers: http://www.cuj.com/documents/s=8042/cuj0002meyers/
Andrei Alexandrescu: http://groups.google.com/groups
?selm=GrE7F4.1s0x%40beaver.cs.washington.edu

As pointed out in my previous reply to "Julie", this is not just
about a paranoid fear of "slicing". It is about clean design.
Why create a new type when all you want to do is extend the
interface of an existing class?

There are a few reasons to prefer extending an interface with
non-member functions, but only one dogmatic argument in favor
of using derivation: that the obj.f() notation would somehow be
superior to f(obj).

Yes, it is unfortunate that such a dichotomy exists in C++ within
the interface to a class, between member and non-member functions.
But is it reasonable to make compromises in your designs only
because you favor one notation over the other?
Not in my opinion, nor in the opinion of the authors above.


Regards,
Ivan
 
I

Ivan Vecerina

Pete Becker said:
Sigh. It has everything to do with the assertion that the destructors
of classes that are intended to be derived from always be virtual or
protected.

But they have nothing to do with my assertion that PJ's statement
was misleading, because many will understand that it applies to
containers etc, while it only really applies to specific classes
that many readers wouldn't even know the exact purpose of.

This is the core point I have been trying to make, and you do
not seem to have made any concrete effort to dispute it.


The rest of the discussion is a waste of time, because it has
already been debated way too often. Obviously you do not share
my (or Herb's) opinion that the standard library should make
extra efforts to avoid potential or even hypothetical misuse.

Also, this endless debate only served to distract from the
other valid reasons why deriving from std::bitset is probably
not a good idea. This was very unfortunate.


Regards,
Ivan
 
P

Pete Becker

Ivan said:
But they have nothing to do with my assertion that PJ's statement
was misleading, because many will understand that it applies to
containers etc, while it only really applies to specific classes
that many readers wouldn't even know the exact purpose of.

"I don't agree with it" is not the same as "it's misleading."
 
I

Ivan Vecerina

Pete Becker said:
"I don't agree with it" is not the same as "it's misleading."

I do agree with the statement. However, its author (PJ) should have
specified to which classes it applies. Because standard containers
and std::bitset definitely aren't "clearly intended to serve as
base( classe)s even though they have no virtual destructors".
[I asked you, and it seems even you would not try to defend this...].

The statement was misleading in its context, as it was in no way
associated with templates such as unary_function, binary_function, etc.

You haven't contradicted either the assertion that the destructor
of the latter classes conceptually could be protected. Your have only
voiced the opinion that translating this concept into practice is not
worth the effort. I understand this point of view, but I believe it
could have been expressed in a kinder fashion.

I understand your time is precious, and I've spent enough of mine
on this too. So let's close it.
 
P

Pete Becker

Ivan said:
Pete Becker said:
"I don't agree with it" is not the same as "it's misleading."

I do agree with the statement. However, its author (PJ) should have
specified to which classes it applies. Because standard containers
and std::bitset definitely aren't "clearly intended to serve as
base( classe)s even though they have no virtual destructors".
[I asked you, and it seems even you would not try to defend this...].

You presume too much.
The statement was misleading in its context, as it was in no way
associated with templates such as unary_function, binary_function, etc.
Sigh.


You haven't contradicted either the assertion that the destructor
of the latter classes conceptually could be protected. Your have only
voiced the opinion that translating this concept into practice is not
worth the effort. I understand this point of view, but I believe it
could have been expressed in a kinder fashion.

Sigh.
 
A

Alexander Terekhov

Ivan Vecerina wrote:
[...]
Could you suggest a counter-example?

Think of something along the lines of boost/tr1 share_ptr<> with
deleters. You can inherit from "base classes" without virtual
destructors and even expose (if needed, on a case-by-case basis)
"base pointers" (smart ones) that will trigger proper destruction.

Oder?

regards,
alexander.
 
T

Tom Widmer

*methods*?

Because doing it:
- creates potential slicing issues (during object copies)
- adds an opportunity for undefined behavior (during delete & array access)
- contradicts the "keep it simple" principle by adding a new type for no
purpose (new class in your hierarchy tree, and potentially
conversions/operators to add).
- may require unnecessary object copying/conversions when interfacing
with code that uses the type being derived from (this is especially true
when deriving from std::string or std::vector).
Do you disagree?

FWIW, I agree entirely. I'm not particularly opposed to deriving from
containers because of the unlikely possibility of UB, but for the
other reasons you mention, which are more important.

If you are creating a domain class, then publically deriving from a
container is crazy, since you then can't maintain invariants. For
utility code, it makes far more sense to add non-member functions, or
generic algorithms. In neither case is public derivation from a
std::container the simplest or cleanest solution.

Tom
 
I

Ivan Vecerina

Alexander Terekhov said:
Ivan Vecerina wrote:
[...]
Could you suggest a counter-example?

Think of something along the lines of boost/tr1 share_ptr<> with
deleters. You can inherit from "base classes" without virtual
destructors and even expose (if needed, on a case-by-case basis)
"base pointers" (smart ones) that will trigger proper destruction.

Well... I guess you can make such a code construction. But I
cannot say that this is a satisfactory answer, because the
description of the idiom and of its purpose is weak.
How would these "base pointers" be used if the base
class has no virtual function, and why can't the base class
destructor be virtual?

So I think the challenge remains open :

Is there a useful C++ idiom where a class that is being derived
from has to have a public and non-virtual destructor?

Ich habe keine Ahnung - ich habe selbst kein Beispiel gefunden!

Merci ;)
Ivan
 

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

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top