Topic: RTTI and Type Relations


Author: evan@hplerk.hpl.hp.com (Evan Kirshenbaum)
Date: Mon, 22 Nov 1993 20:09:16 GMT
Raw View
I just finished "Run-Time Type Identification for C++ (Revised yet
again)" by Stroustrup and Lenkov, and I was wondering if anyone could
go into more depth about why type relations were omitted, and tell me
the recommended way to work around their absence

On page 18, they say

    We considered defining <, <=, etc. on Type_info objects to express
    relationships in a class hierarchy.  That is easy, but too cute.
    It also suffers from the problems with an explicit type
    comparison operation as described in a    1.  We need a cast in any
    event so we can just as well use a dynamic cast.

I can understand why they prefer that you say

    if (Drvd *dp = dynamic_cast<Drvd *>(bp))
    {
      ...
    }

rather than

    if (typeid(*dp) <= typeid(Drvd))
    {
      Drvd *dp = (Drvd *)bp;
      ...
    }

but this is not the only situation in which type relations are useful.

I just got finished implementing my own type tag system (although I
would have preferred to use a standard facility, and will move to the
standard when it is implemented).  One of the uses of the tags was in
what's essentially an event system, in which handlers are registered
for "Events of this class or a subclass"; roughly:

    class Event
    {
    public:
      typedef Boolean (*Handler)(Event &);
      static void Register(Type_info *, Handler);
      Boolean post();
    private:
      static Stack<Type_Info *, Handler> handlers;
    };

    Boolean Event::post()
    {
      for (int i=0; i<handlers.size(); i++)
      {
        if (typeid(*this) <= *handlers[i].key)
        {
          return (*handlers[i].value)(*this);
        }
      }
    }

Similarly, we have a situation in which we want to pass in a tag for
an abstract base class and look up in a table a function which will
generate an instance of a concrete subclass of that class.  In this
case, the keys in the table are more specific than the one being
looked up.

I don't see how to do either of these without being able to test
whether one type is an ancestor of another.  [I could use the same
scheme I use now, requiring each tagged class to have a static member
whose constructor  explicitly registers its parentage, but it would be
much nicer if the compiler guaranteed to get it right.]

It would also be nice if there were some metric on the distance
between two tags so that I could tell which handler (in a given frame)
is the "most specific" for a given event.

Evan Kirshenbaum         +------------------------------------
    HP Laboratories         | It is a popular delusion that the
    3500 Deer Creek Road, Building 26U | government wastes vast amounts of
    Palo Alto, CA  94304        | money through inefficiency and sloth.
           | Enormous effort and elaborate
    kirshenbaum@hpl.hp.com        | planning are required to waste this
    (415)857-7572         | much money
           |                   P.J. O'Rourke