Topic: ANSI RTTI: Botch in type_info class
Author: kanze@us-es.sel.de (James Kanze)
Date: 07 Apr 1994 13:56:00 GMT Raw View
In article <2n7nno$ncl@seattle.polstra.com> jdp@polstra.com (John
Polstra) writes:
|> It seems to me that there has been a bad design decision made in
|> choosing to use a named member function
|> int type_info::before(const type_info&) const
|> as the ordering predicate for the class type_info. There is a very good
|> reason to overload the "<" operator for this purpose instead:
|> int type_info::operator<(const type_info&) const
|> Here is the reason. There are many situations in which one might want
|> to use class type_info as the key of an associative map. (Stroustrop
|> discusses the usefulness of this in his book.) If the map class is
|> implemented as an ordered map (e.g., some sort of binary search tree)
|> then it needs to be able to determine the relative ordering between any
|> two objects of its key type. To be truly general, the ordered map
|> class must use the operator "<" (or, of course ">") for this.
|> Otherwise, the map cannot be used with a built-in type as its key.
I think that using an overloaded operator for such a function is a
(frequent) bad design decision.
Generally, in maps and such, I expect either that the class use a
global function (eg: compare) or to be required to register the
function. The main reason is to decouple the total ordering required
(which may be arbitrary) from the semantic implications of <, >, etc.
For example, I have a class SetOfChar, which implements a set of
characters. This class has a compare function (as do all of my
classes) which returns -1, 0 or 1 according to whether the first set
is ordered below, equal or above the second. The ordering thus
defined is totally arbitrary. The class also defines <, <=, > and >=.
These define the sub-/superset relationship, which would seem
intuitively correct from a user point of view. Of course, this
relationship is only a partial ordering; any map, etc. which uses the
< from this class will fail.
As the ordering of type_info is totally arbitrary, I think it would
have been a design error to overload operator< for it. It is much
better to use a named function. (I like compare, and the three valued
return, but there are no technical reasons to prefer one name over
another.)
Interestingly, though the committee felt it necessary to provide a
total ordering, they didn't find it necessary to insist on a hash
function. A shame: my map class uses hash coding:-(.
--
James Kanze email: kanze@lts.sel.alcatel.de
GABI Software, Sarl., 8 rue du Faisan, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: maxtal@physics.su.OZ.AU (John Max Skaller)
Date: Sat, 9 Apr 1994 22:45:58 GMT Raw View
In article <2n7nno$ncl@seattle.polstra.com> jdp@polstra.com (John Polstra) writes:
>Recently I was reading about the new C++ feature for RTTI in
>Stroustrop's new book, "The Design and Evolution of C++". (It's an
>interesting book, by the way.)
>
>It seems to me that there has been a bad design decision made in
>choosing to use a named member function
>
> int type_info::before(const type_info&) const
>
>as the ordering predicate for the class type_info. There is a very good
>reason to overload the "<" operator for this purpose instead:
>
> int type_info::operator<(const type_info&) const
>
Rot :-)
Just define it yourself.
int operator<(const type_info& a, const type_info &b)
{
return a.before(b);
}
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd, CSERVE:10236.1703
6 MacKay St ASHFIELD, Mem: SA IT/9/22,SC22/WG21
NSW 2131, AUSTRALIA
Author: jdp@polstra.com (John Polstra)
Date: 29 Mar 1994 11:11:03 -0800 Raw View
In article <DAG.94Mar29085334@bellman.control.lth.se>,
Dag Bruck <dag@control.lth.se> wrote:
> >>>>> On 28 Mar 1994 15:03:20 -0800, jdp@polstra.com (John Polstra) said:
>
> John> It seems to me that there has been a bad design decision made in
> John> choosing to use a named member function
>
> John> int type_info::before(const type_info&) const
>
> John> as the ordering predicate for the class type_info. There is a very good
> John> reason to overload the "<" operator for this purpose instead:
>
> John> int type_info::operator<(const type_info&) const
>
> The reason is that we were afraid that "<" would be regarded as
> something that describes type relations, in particular that
>
> typeid(A) < typeid(B)
>
> implies that that B is derived from A. That is not the case, so we
> picked a name ("before") that we hoped would not give the same
> associations. However, your observation about the implamentation of
> maps is correct.
Your concerns about potential misinterpretation of the meaning of "<"
would form a good basis for a decision if there were no other
considerations. But as the example involving maps shows, you are
sacrificing significant and useful functionality by not using "<".
Potential misinterpretation can be documented away. But lost
functionality is just ... lost. I think that functionality should
prevail. A C++ user who isn't in the habit of reading the manual is
never going to progress to the point where he'd be ready to use RTTI,
anyway.
In the ANSI/ISO discussions, did the issue of lost functionality caused
by the choice of type_info::before() come up for discussion?
Is it too late to reconsider?
--
John Polstra jdp@polstra.com
John D. Polstra & Co., Inc. Phone (206) 932-6482
Seattle, Washington USA Fax (206) 935-1262
"Self-knowledge is always bad news." -- John Barth
Author: dag@control.lth.se (Dag Bruck)
Date: 29 Mar 1994 20:56:32 GMT Raw View
>>>>> On 29 Mar 1994 11:11:03 -0800, jdp@polstra.com (John Polstra) said:
>> Your concerns about potential misinterpretation of the meaning of "<"
>> would form a good basis for a decision if there were no other
>> considerations. But as the example involving maps shows, you are
>> sacrificing significant and useful functionality by not using "<".
Well, I think you're overstating the problem. First, you can define
the operator afterwards:
bool operator < (const type_info& t1, const type_info& t2)
{ return t1.before(t2); }
If you don't like that approach, you can always write a specialization
of the Map functions that use operator< that use type_info::before
instead.
We may have arrived at the wrong decision in your view, but everything
is not lost.
>> Is it too late to reconsider?
No.
-- Dag
Author: jdp@polstra.com (John Polstra)
Date: 29 Mar 1994 23:02:51 -0800 Raw View
In article <DAG.94Mar29225633@bellman.control.lth.se>,
Dag Bruck <dag@control.lth.se> wrote:
> >>>>> On 29 Mar 1994 11:11:03 -0800, jdp@polstra.com (John Polstra) said:
> >> Your concerns about potential misinterpretation of the meaning of "<"
> >> would form a good basis for a decision if there were no other
> >> considerations. But as the example involving maps shows, you are
> >> sacrificing significant and useful functionality by not using "<".
>
> Well, I think you're overstating the problem.
> ...
> We may have arrived at the wrong decision in your view, but everything
> is not lost.
I don't mean to overstate the problem. It's not an earth-shaking
problem. There are plenty of ways to work around it. I understand
that. I view it as an annoying blemish that goes a little bit beyond
being just a question of taste or programming style, because it renders
the type_info class unusable *directly* as the key for a general-purpose
ordered map class. Fine. We all have bigger irritations than this one
to deal with every day. In context, it's not that big of a deal.
But ... but! ... it's a blemish that the standards writers still have a
chance to eliminate, if they decide they agree with my arguments.
What a rare and fleeting opportunity! Seize the moment!
Have a nice day :-)
--
John Polstra jdp@polstra.com
John D. Polstra & Co., Inc. Phone (206) 932-6482
Seattle, Washington USA Fax (206) 935-1262
"Self-knowledge is always bad news." -- John Barth
Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 31 Mar 94 14:59:12 GMT Raw View
jdp@polstra.com (John Polstra @ Polstra & Co., Seattle, WA) write
> I don't mean to overstate the problem. It's not an earth-shaking
> problem. There are plenty of ways to work around it. I understand
> that. I view it as an annoying blemish that goes a little bit beyond
> being just a question of taste or programming style, because it renders
> the type_info class unusable *directly* as the key for a general-purpose
> ordered map class. Fine. We all have bigger irritations than this one
> to deal with every day. In context, it's not that big of a deal.
>
> But ... but! ... it's a blemish that the standards writers still have a
> chance to eliminate, if they decide they agree with my arguments.
> What a rare and fleeting opportunity! Seize the moment!
Maybe calling the ordering function `before' was a botch, maybe not.
Maybe calling it `<' would be a botch, maybe not.
How would we know? (a serious question, not rhetoric).
I have had enough requests for `A < B' meaning B is derived from A to be
reluctant to introduce `<' for any object representing type with another
meaning. It would undoubtedly cause confusion. One argument for `before'
is that it more or less force programmers to read the manual. In the case
of `<' many (most?) would guess, and many would guess wrong and get burned.
The issue is not clear cut. If you want `<' to mean `before' try
int operator<(const type_info& a, const type_into& b)
{
return a.before(b);
}
Author: jdp@polstra.com (John Polstra)
Date: 28 Mar 1994 15:03:20 -0800 Raw View
Recently I was reading about the new C++ feature for RTTI in
Stroustrop's new book, "The Design and Evolution of C++". (It's an
interesting book, by the way.)
It seems to me that there has been a bad design decision made in
choosing to use a named member function
int type_info::before(const type_info&) const
as the ordering predicate for the class type_info. There is a very good
reason to overload the "<" operator for this purpose instead:
int type_info::operator<(const type_info&) const
Here is the reason. There are many situations in which one might want
to use class type_info as the key of an associative map. (Stroustrop
discusses the usefulness of this in his book.) If the map class is
implemented as an ordered map (e.g., some sort of binary search tree)
then it needs to be able to determine the relative ordering between any
two objects of its key type. To be truly general, the ordered map
class must use the operator "<" (or, of course ">") for this.
Otherwise, the map cannot be used with a built-in type as its key.
More concretely, if I have a map class
template <class Key, class Value> class Map { ... };
and I have implemented it to use the operators "==" and "<" for
comparing Keys, then I can create an instance of Map<int, Anything> and
it will work. And, if class type_info had "<" as its ordering
predicate, I could also create an instance of Map<type_info, Anything>
and it would work. As the type_info class is defined currently (at
least in the book), I can't use it that way.
I understand the many ways a programmer can work around this problem.
But it seems silly to require a workaround when a simple change to the
ANSI definition would eliminate the need for one entirely.
Is there some reason the class is defined the way it is currently?
PS - Also, since we are getting a new built-in "bool" type, I would hope
that the type_info predicates will be modified to return that instead of
"int".
--
John Polstra jdp@polstra.com
John D. Polstra & Co., Inc. Phone (206) 932-6482
Seattle, Washington USA Fax (206) 935-1262
"Self-knowledge is always bad news." -- John Barth
Author: dag@control.lth.se (Dag Bruck)
Date: 29 Mar 1994 06:53:33 GMT Raw View
>>>>> On 28 Mar 1994 15:03:20 -0800, jdp@polstra.com (John Polstra) said:
John> It seems to me that there has been a bad design decision made in
John> choosing to use a named member function
John> int type_info::before(const type_info&) const
John> as the ordering predicate for the class type_info. There is a very good
John> reason to overload the "<" operator for this purpose instead:
John> int type_info::operator<(const type_info&) const
The reason is that we were afraid that "<" would be regarded as
something that describes type relations, in particular that
typeid(A) < typeid(B)
implies that that B is derived from A. That is not the case, so we
picked a name ("before") that we hoped would not give the same
associations. However, your observation about the implamentation of
maps is correct.
John> PS - Also, since we are getting a new built-in "bool" type, I would hope
John> that the type_info predicates will be modified to return that instead of
John> "int".
The working paper has been changed in many other places to use "bool",
so this will certainly be done for type_info predicates as well, if it
hasn't been done already.
-- Dag