Topic: RTTI not all its cracked up to be...


Author: tminkoff@cts.com (Tony Minkoff)
Date: 1997/04/18
Raw View

In article <5j39ia$mo@netlab.cs.rpi.edu>,
Damian Conway <damian@cs.monash.edu.au> wrote:
>Actually, getting multimethods right would have tacked another year or
>two onto the standardization effort, so we should be grateful it was
>not attempted.

At the same time, it would be a shame to see a useful feature
permanently excluded from the language simply because there wasn't
enough time to get the standard right when the standards committee
met.  Will there be further enhancements to the language, or will the
standard, once adopted, be considered the complete and final definition
of the language?

--
Tony Minkoff
tminkoff@cts.com
anthony_minkoff@ccmail.mitchell.com

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Bradd W. Szonye" <bradds@concentric.net>
Date: 1997/04/20
Raw View
Tony Minkoff <tminkoff@cts.com> wrote in article
<fjh-970418-162044@cs.mu.oz.au>...
>
>
> Will there be further enhancements to the language, or will the
> standard, once adopted, be considered the complete and final definition
> of the language?

As Steve Clamage recently pointed out, standards go through a five-year
"reduced activity" period after approval. This gives the standards body
time to accept comments and complaints and to issue defect reports,
normative amendments, and technical corrigenda. After the five-year period,
the committee reconvenes to determine whether the language merits a
complete review and revision. Ada, Algol, COBOL, FORTRAN, and now C have
all gone through this process at least once; all have had at least one
major revision (except C, which is in the process of defining the
revision).

For example, C became an International Standard in 1990. After that, the C
committee issued several Defect Reports to address minor weaknesses in the
standard or clarify ambiguities. The Normative Amendment to C added
subclauses to clause 7 (library) to provide support for
internationalization at compile- and run-time; this addressed some issues
that never reached consensus before the original publication of the
standard. The two Technical Corrigenda made several clarifications and
minor amendments to the original standard to make clarifications and
corrections of varying importance. Some time after 1995 (five years), the C
committee decided to reopen the standard for revision; the revision will
probably become an International Standard some time between 1997 and 1999.

(I hope I have all my facts straight here. The last time I made a sweeping
statement about what "The Committee" does, I was way off base, and Mr.
Clamage set me straight. Please remember that I'm not [yet] a member of the
ANSI or ISO work groups and take this with a grain of salt. What follows
from here is mostly my opinion, not fact.)

The C++ language will go through the same process. I think that likely
candidates for Normative Amendments to C++ are those major features which
were well-designed, implemented, and tested, and would have been accepted
but for lack of time. The most obvious example of this is the set of
hash-based containers added to the Standard Template Library shortly after
the C++ library was closed to further major changes. I wouldn't expect this
Amendment to appear, however--if at all--until vendors stabilize their
"comforming" implementations and the rest of the library sees significant
real-world testing.

Technical Corrigenda are likely to address things like overspecified,
underspecified, and ambiguous requirements. Is type_info::before required
to be a total order over the types in a program? Is the random-access
requirement on sort algorithms overspecified? Shouldn't make_heap have 2N
complexity rather than 3N complexity? Does NlogN mean O(NlogN) or exactly
NlogN?

Finally, sometime between 2002 and 2004 (assuming that this isn't the
"Judgment Day" millenium), the committee will consider a complete revision
to the standard. The five-year waiting period makes sense: without it, no
language standard would ever stabilize. Consider it a cooling-off period,
to give people time to consider which of the many things that didn't make
it into the standard are actually important. I'm sure that many people
wanted an immediate revision of C in 1990 as well. Now, seven years later,
at least a few people wish that C9X were a simple re-affirmation of C90.
--
Bradd W. Szonye
bradds@concentric.net

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1997/04/15
Raw View
Marco Dalla Gasperina <marcodg@vcd.hp.com> wrote:
: Oleg Zabluda <zabluda@math.psu.edu> wrote in article
: <5ijee6$blj@netlab.cs.rpi.edu>...
: > class Event{
: >  public:
: >    virtual void handle() = 0;
: > }
: >
: > class SmartEvent : public Event {
: >  public:
: >   virtual void handle(){/*....*/}
: > };
: >
: > class DumbEvent : public Event {
: > public:
: >   virtual void handle(){/*....*/}
: > };
: >
: > int main(void)
: > {
: >  Event* Test = new SmartEvent();
: >  Test->handle();
: > }
: >

: Benjamin Scherrey's code does have one advantage over yours, however.
: In his, events are separate from their handlers.  This extremely
: important if the same event can have different effects at different
: times.  In your code, you would need to do something like this:

: class SmartEvent {
: public:
:     virtual void handle( Circumstance eventContext ) {
:         switch ( eventContext ) {
:         case during_flood : // handle code for a flood
:         case during_fire : // handle code for a fire
:              ....
:     }
: }

: In which you have to add a switch statement to every
: event every time a different circumstance is created.

Yes, but the alternative is even worse. You'd have to stuff
absolutely the same amount of code into the EventHandler.
You get the advantage of concentrating it in one place, of
course.

But the advantage IMHO is far outweighed by the disadvantage
of having a much more complex relations between classes.
In my experience, this is exactly where software development
difficulties are. Writing each individual class is trivial,
as soon as the interface is defined. This is true for all,
but the negligible number of cases.

This is true even for a human brain, which consists of a number
of very simple devices - neurons. Interactions between them
is where the whole story is.

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.
[note to moderator snipped --mod]
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Jason Merrill <jason@cygnus.com>
Date: 1997/04/15
Raw View
>>>>> Tony Minkoff <tminkoff@cts.com> writes:

> I vaguely remember reading something about a proposed C++ extension for a
> kind of virtual method in which the particular method called would be
> chosen not by the class of a single object, but rather by the classes of
> a set of objects.  I think they were called polyvirtual functions, or
> something like that.

The Common Lisp Object System (CLOS) supports such methods, and calls
them multi-methods.

> And, if memory serves, the proposed extension was discussed in the
> standards committee, and turned down.  I don't know why.

Probably because it was deemed too complex for the percieved benefit,
since you can use double dispatch to simulate multi-methods in cases
where they are necessary.

Jason

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: mbresnahan1@mmm.com
Date: 1997/04/16
Raw View
[Moderator's note: This discussion no longer has much to do with C++
standardization.  Followups are being directed by default to
comp.lang.c++.moderated. mha]

Paul D. DeRocco wrote:
>
> Benjamin Scherrey wrote:
> >
> >         Take the following situation :
> >
> > class Event;    // polymorphic class capable of supporting dynamic_cast
> > class SmartEvent : public Event { ... };
> > class DumbEvent : public Event { ... };
> > class ..nextevent ...
> >
> >         Without a giant set of if/else groups attempting hundreds of
> > dynamic
> > casts, how do I implement the following functionality :
> >
> > class EventHandler
> > {
> >         void handle( const SmartEvent& event ) {...handle the SmartEvent
> > ...}
> >         void handle( const DumbEvent& event ) {...handle the DumbEvent
> > ...}
> > };
> >
> > void main( void )
> > {
> >         EventHandler Handler;
> >         Event* Test = new SmartEvent();
> >
> >         Handler.handle( *Test );            // Why can't RTTI resolve
> > this?
> > }
> >
> >         Does anyone have any suggestions for efficient workarounds that
> > will
> > allow me to achieve this functionality? I need to handle events without
> > knowing their actual inherited types at compiler time.

I didn't read the original post and it has expired on my news server,
but  this looks like a classic problem for the visitor pattern.

How about this:

class EventHandler {
public:
    virtual void visit( const SmartEvent &) = 0;
    virtual void visit( const DumbEvent &) = 0;
};

class Event {
puclic:
    virtual void accept( EventHandler &h) = 0;
};

class MyEventHandler {
public:
    virtual void visit( const SmartEvent &) { /* handle smart event */ }
    virtual void visit( const DumbEvent &) { /* handle dumb event */ }
};

class DumbEvent {
puclic:
    virtual void accept( EventHandler &h) { h.visit( *this); }
};

class SmartEvent : public Event {
public:
    virtual void accept( EventHandler &h) { h.visit( *this); }
};

int main() {

    MyEventHandler handler;
    Event *ev = new SmartEvent();
    ev.accept( handler);
}

Whalla, no rtti!

I'm confused why someone didn't mention this solution.  Am I missing
something?

MikeB
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: damian@cs.monash.edu.au (Damian Conway)
Date: 1997/04/16
Raw View
Jason Merrill <jason@cygnus.com> writes:

>>>>>> Tony Minkoff <tminkoff@cts.com> writes:

>> And, if memory serves, the proposed [multimethods] extension was
>> discussed in the standards committee, and turned down. I don't know why.

Anyone have a copy of such a proposal?
I'd be very interested to see the details.

> Probably because it was deemed too complex for the percieved benefit,
> since you can use double dispatch to simulate multi-methods in cases
> where they are necessary.

...and you don't care much about performance or maintainability :-(

Actually, getting multimethods right would have tacked another year or
two onto the standardization effort, so we should be grateful it was
not attempted.

damian
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]





Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/04/12
Raw View
Oleg Zabluda wrote:
<snip> (Advocates virtual function in lieu of RTTI if-else loop.)
> 1. Eliminated 1 class.
> 2. Works much faster (no run-time RTTI).
> 3. Neither *Event nor EventHandler have to be changed or recompiled
>    if you add class DumbestEvent.
>
> Oleg.

1. True, but not a big deal.
3. The essence of the issue, IMHO. (Much better object design!)

2. Mmmm. (?) How much faster, exactly? Based on what compilers, on what
platforms, with what compile switches?  (I've seen a lot of screwy
things advocated because "they're faster", so I tend to be skeptical
when I see this argument.)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with
your
                newsreader.  If that fails, use
mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: "Paul D. DeRocco" <strip_these_words_pderocco@ix.netcom.com>
Date: 1997/04/13
Raw View
Benjamin Scherrey wrote:
>
>         Take the following situation :
>
> class Event;    // polymorphic class capable of supporting dynamic_cast
> class SmartEvent : public Event { ... };
> class DumbEvent : public Event { ... };
> class ..nextevent ...
>
>         Without a giant set of if/else groups attempting hundreds of
> dynamic
> casts, how do I implement the following functionality :
>
> class EventHandler
> {
>         void handle( const SmartEvent& event ) {...handle the SmartEvent
> ...}
>         void handle( const DumbEvent& event ) {...handle the DumbEvent
> ...}
> };
>
> void main( void )
> {
>         EventHandler Handler;
>         Event* Test = new SmartEvent();
>
>         Handler.handle( *Test );            // Why can't RTTI resolve
> this?
> }
>
>         Does anyone have any suggestions for efficient workarounds that
> will
> allow me to achieve this functionality? I need to handle events without
> knowing their actual inherited types at compiler time.
>
>         thanx & later,
>
>                 Ben Scherrey

If the two EventHandler::handle functions needed to be virtual, you'd be
stuck, because you can't make C++ automatically select a function based
on two types. But since they are non-virtual, you can accomplish what
you want by making handle() a virtual function of Event instead of
EventHandler.

By the way, are you still with Team Borland, or is that ancient history?

--

Ciao,
Paul D. DeRocco
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]







Author: "Marco Dalla Gasperina" <marcodg@vcd.hp.com>
Date: 1997/04/13
Raw View
Oleg Zabluda <zabluda@math.psu.edu> wrote in article
<5ijee6$blj@netlab.cs.rpi.edu>...
> class Event{
>  public:
>    virtual void handle() = 0;
> }
>
> class SmartEvent : public Event {
>  public:
>   virtual void handle(){/*....*/}
> };
>
> class DumbEvent : public Event {
> public:
>   virtual void handle(){/*....*/}
> };
>
> int main(void)
> {
>  Event* Test = new SmartEvent();
>  Test->handle();
> }
>
> Note how superior it is to your code:
>
> 1. Eliminated 1 class.
> 2. Works much faster (no run-time RTTI).
> 3. Neither *Event nor EventHandler have to be changed or recompiled
>    if you add class DumbestEvent.

Benjamin Scherrey's code does have one advantage over yours, however.
In his, events are separate from their handlers.  This extremely
important if the same event can have different effects at different
times.  In your code, you would need to do something like this:

class SmartEvent {
public:
    virtual void handle( Circumstance eventContext ) {
        switch ( eventContext ) {
        case during_flood : // handle code for a flood
        case during_fire : // handle code for a fire
             ....
    }
}

In which you have to add a switch statement to every
event every time a different circumstance is created.

marco




---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: John Lilley <jlilley@empathy.com>
Date: 1997/04/14
Raw View
Benjamin Scherrey wrote:
>how do I implement the following functionality :

Oops!  In my previous post, the invokeHandler() methods should have been
virtual.

john lilley

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: tminkoff@cts.com (Tony Minkoff)
Date: 1997/04/14
Raw View
In article <5iqlji$dvr@netlab.cs.rpi.edu>,
Marco Dalla Gasperina <marcodg@vcd.hp.com> wrote:
 >Oleg Zabluda <zabluda@math.psu.edu> wrote in article
 ><5ijee6$blj@netlab.cs.rpi.edu>...
 >> class Event{
 >>  public:
 >>    virtual void handle() = 0;
 >> }
 >>
 >> class SmartEvent : public Event {
 >>  public:
 >>   virtual void handle(){/*....*/}
 >> };
 >>
 >> class DumbEvent : public Event {
 >> public:
 >>   virtual void handle(){/*....*/}
 >> };
 >>
 >> int main(void)
 >> {
 >>  Event* Test = new SmartEvent();
 >>  Test->handle();
 >> }
 >>
 >> Note how superior it is to your code:
 >>
 >> 1. Eliminated 1 class.
 >> 2. Works much faster (no run-time RTTI).
 >> 3. Neither *Event nor EventHandler have to be changed or recompiled
 >>    if you add class DumbestEvent.
 >
 >Benjamin Scherrey's code does have one advantage over yours, however.
 >In his, events are separate from their handlers.  This extremely
 >important if the same event can have different effects at different
 >times.  In your code, you would need to do something like this:
 >
 >class SmartEvent {
 >public:
 >    virtual void handle( Circumstance eventContext ) {
 >        switch ( eventContext ) {
 >        case during_flood : // handle code for a flood
 >        case during_fire : // handle code for a fire
 >             ....
 >    }
 >}
 >
 >In which you have to add a switch statement to every
 >event every time a different circumstance is created.
 >
 >marco

It seems what we have here is a semantic (handle an event) whose
particular
behavior is determined by the class of event and by the class of event
handler.

I vaguely remember reading something about a proposed C++ extension for
a kind of virtual method in which the particular method called would be
chosen not by the class of a single object, but rather by the classes of
a set of objects.  I think they were called polyvirtual functions, or
something like that.  And, if memory serves, the proposed extension was
discussed in the standards committee, and turned down.  I don't know
why.
This ring a bell with anybody?  The conclusions of the standards
committee wrt polyvirtual functions might shed some light on this
event-handling problem we have been discussing.
--
Tony Minkoff
tminkoff@cts.com
anthony_minkoff@ccmail.mitchell.com
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with
    ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu
    ]
[ FAQ:
http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:
http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu
    ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: scherrey@proteus-tech.com (Benjamin Scherrey)
Date: 1997/04/10
Raw View
        I must say that, as impressed as I am that the C++ standard has
evolved very intelligently and while I agree with nearly all the
pricipled
arguments that have resulted in the trade-offs this standard achieves, I
am
disappointed in how limited RTTI really is in, what I consider, some
pretty
obvious, commonly required, and easily implemented (I presume)
functionality.

        Take the following situation :

class Event;    // polymorphic class capable of supporting dynamic_cast
class SmartEvent : public Event { ... };
class DumbEvent : public Event { ... };
class ..nextevent ...

        Without a giant set of if/else groups attempting hundreds of
dynamic
casts, how do I implement the following functionality :

class EventHandler
{
        void handle( const SmartEvent& event ) {...handle the SmartEvent
...}
        void handle( const DumbEvent& event ) {...handle the DumbEvent
...}
};

void main( void )
{
        EventHandler Handler;
        Event* Test = new SmartEvent();

        Handler.handle( *Test );            // Why can't RTTI resolve
this?
}

        Does anyone have any suggestions for efficient workarounds that
will
allow me to achieve this functionality? I need to handle events without
knowing their actual inherited types at compiler time.

        thanx & later,

                Ben Scherrey

//
//  Benjamin Scherrey                   scherrey@proteus-tech.com
//  Proteus Technologies, Inc.          Atlanta, Georgia U.S.A.
//  (770) 454-1013 vox                  (770) 986-9876 fax
//  http://www.proteus-tech.com         33.886727N by 84.286969W
//

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with
your
                newsreader.  If that fails, use
mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Oleg Zabluda <zabluda@math.psu.edu>
Date: 1997/04/10
Raw View
Benjamin Scherrey <scherrey@proteus-tech.com> wrote:
: I must say that, as impressed as I am that the C++ standard has
: evolved very intelligently and while I agree with nearly all the
: pricipled
: arguments that have resulted in the trade-offs this standard achieves,
I
: am
: disappointed in how limited RTTI really is in, what I consider, some
: pretty
: obvious, commonly required, and easily implemented (I presume)
: functionality.

The functionality you want is the Wrong Way (Tm). If the only use
for RTTI would be the stuff you want, RTTI would have never been
adopted. It was adopted for other purposes, where you can't get
around it, or even if you can, it's beneficial to have a
language-supported standard way.

:         Take the following situation :

: class Event;    // polymorphic class capable of supporting
dynamic_cast
: class SmartEvent : public Event { ... };
: class DumbEvent : public Event { ... };
: class ..nextevent ...

:         Without a giant set of if/else groups attempting hundreds of
: dynamic
: casts, how do I implement the following functionality :

: class EventHandler
: {
:         void handle( const SmartEvent& event ) {...handle the
SmartEvent
: ...}
:         void handle( const DumbEvent& event ) {...handle the DumbEvent
: ...}
: };

: void main( void )
: {
:         EventHandler Handler;
:         Event* Test = new SmartEvent();

:         Handler.handle( *Test );            // Why can't RTTI resolve
: this?
: }

Because C++ provides a better way - virtual functions.

class Event{
 public:
   virtual void handle() = 0;
}

class SmartEvent : public Event {
 public:
  virtual void handle(){/*....*/}
};

class DumbEvent : public Event {
public:
  virtual void handle(){/*....*/}
};

int main(void)
{
 Event* Test = new SmartEvent();
 Test->handle();
}

Note how superior it is to your code:

1. Eliminated 1 class.
2. Works much faster (no run-time RTTI).
3. Neither *Event nor EventHandler have to be changed or recompiled
   if you add class DumbestEvent.

Oleg.
--
Life is a sexually transmitted, 100% lethal disease.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with
your
                newsreader.  If that fails, use
mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: "Marco Dalla Gasperina" <marcodg@vcd.hp.com>
Date: 1997/04/11
Raw View
Benjamin Scherrey <scherrey@proteus-tech.com> wrote in article
<5iip4q$5bb@netlab.cs.rpi.edu>...
>         Without a giant set of if/else groups attempting hundreds of
> dynamic
> casts, how do I implement the following functionality :
>
> class EventHandler
> {
>         void handle( const SmartEvent& event ) {...handle the SmartEvent
> ...}
>         void handle( const DumbEvent& event ) {...handle the DumbEvent
> ...}
> };
>
> void main( void )
> {
>         EventHandler Handler;
>         Event* Test = new SmartEvent();
>
>         Handler.handle( *Test );  // Why can't RTTI resolve this?
> }
>
> Does anyone have any suggestions for efficient workarounds that will
> allow me to achieve this functionality? I need to handle events without
> knowing their actual inherited types at compiler time.

In answer to "Why can't RTTI resolve this?", overloading is done on
the static type of the object (in this case Event).

In answer to how to implement it, here is a way that is somewhat
inelegant but easily understood and implemented:

class EventHandler {
public:
    // instead of overloading, have one member for each event
    void handleSmartEvent( const SmartEvent& event );
    void handleDumbEvent( const DumbEvent& event );
};

class Event {
public:
    virtual void handleIt( EventHandler& eh ) = 0;
};

class SmartEvent : public Event {
public:
    void handleIt( EventHandler& eh ) {
        eh.handleSmartEvent( *this );
    }
};

class DumbEvent : public Event {
public:
    void handleIt( EventHandler& eh ) {
        eh.handleDumbEvent( *this );
    }
};

void main( void )
{
    EventHandler Handler;
    Event* Test = new SmartEvent();
    test->handle( Handler );
}

Doing it this way, you allow the event to dispatch itself to the
correct handler.  It is somewhat inelegant in that there is now
a mutual dependency between ALL events and ALL handlers (i.e.
every time a new event is added all the handlers need to change).

marco
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: seurer@rchland.ibm.com (Bill Seurer)
Date: 1997/04/11
Raw View

In article <5iip4q$5bb@netlab.cs.rpi.edu>, scherrey@proteus-tech.com (Benjamin
Scherrey) writes:
|>         Does anyone have any suggestions for efficient workarounds that
|> will
|> allow me to achieve this functionality? I need to handle events without
|> knowing their actual inherited types at compiler time.

Put a member function pointer in Event that points to EventHandler
members.  Set up the value in the constructors of the different
kinds of Events.  Then either use the member function pointer to call the
events or put an inline wrapper function in Event to make the call.
--

- Bill Seurer     ID Tools and Compiler Development      IBM Rochester, MN
  BillSeurer AT vnet.ibm.com                         BillSeurer AT aol.com
  http://members.aol.com/BillSeurer  (replace " AT " with "@" to email me)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: brad@cfar.umd.edu (Brad Stuart)
Date: 1997/04/11
Raw View
Benjamin Scherrey (scherrey@proteus-tech.com) wrote:

: class EventHandler
: {
:         void handle( const SmartEvent& event ) {...handle the SmartEvent
: ...}
:         void handle( const DumbEvent& event ) {...handle the DumbEvent
: ...}
: };

Since the function called depends on the type of event, you need to
use a virtual function in the Event hierarchy.

class Event (Smart, Dumb, whatever)
{
[...]
 virtual void visit_handler( EventHandler &handler )
 { handler.handle( *this ); }
}

Each subclass of Event will override visit_handler, using the same
body. Then  Test->visit_handler() will call the appropriate method,
depending on the polymorphic type of Test.

This is called double-dispatch, or sometimes a Visitor pattern.

Brad

--
| Brad Stuart      brad@cfar.umd.edu
| Center for Automation Research
| University of Maryland, College Park
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: John Lilley <jlilley@empathy.com>
Date: 1997/04/11
Raw View
Benjamin Scherrey wrote:

> class Event;    // polymorphic class capable of supporting dynamic_cast
> class SmartEvent : public Event { ... };
> class DumbEvent : public Event { ... };
>
> how do I implement the following functionality :
>
> class EventHandler {
>     void handle( const SmartEvent& event ) {...}
>     void handle( const DumbEvent& event ) {...}
> };
>
> void main( void ) {
>     EventHandler Handler;
>     Event* Test = new SmartEvent();
>     Handler.handle( *Test );        // Why can't RTTI resolve this?
> }

RTTI cannot resolve this because if you have an object 't' of type 'T*',
then the expression:
   *t
is of type 'T&'.  All overloading happens at compile time, so the "real"
type of 't' is never considered.  This is even true for Java, so don't
get all puffed up at the C++ committee.  There is a clever way to handle
this sort of thing using double-indirection:

class Event {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};
class SmartEvent {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};
class DumbEvent {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};

class EventHandler
{
    void handle( const SmartEvent& event ) {...}
    void handle( const DumbEvent& event ) {...}
};

void main( void )
{
    EventHandler Handler;
    Event* Test = new SmartEvent();
    Test.invokeHandler(Handler);
}

The prevents you from having to write a lot of tests, but still requires
that the invokeHandler() method be duplicated in each event class.

john lilley

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: John Lilley <jlilley@empathy.com>
Date: 1997/04/11
Raw View
Benjamin Scherrey wrote:
>how do I implement the following functionality :

Oops!  In my previous post, the invokeHandler() methods should have been
virtual.

john lilley

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: John Lilley <jlilley@empathy.com>
Date: 1997/04/11
Raw View
Benjamin Scherrey wrote:

> class Event;    // polymorphic class capable of supporting dynamic_cast
> class SmartEvent : public Event { ... };
> class DumbEvent : public Event { ... };
>
> how do I implement the following functionality :
>
> class EventHandler {
>     void handle( const SmartEvent& event ) {...}
>     void handle( const DumbEvent& event ) {...}
> };
>
> void main( void ) {
>     EventHandler Handler;
>     Event* Test = new SmartEvent();
>     Handler.handle( *Test );        // Why can't RTTI resolve this?
> }

RTTI cannot resolve this because if you have an object 't' of type 'T*',
then the expression:
   *t
is of type 'T&'.  All overloading happens at compile time, so the "real"
type of 't' is never considered.  This is even true for Java, so don't
get all puffed up at the C++ committee.  There is a clever way to handle
this sort of thing using double-indirection:

class Event {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};
class SmartEvent {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};
class DumbEvent {
public:
    void invokeHandler(EventHandler& handler) { handler.handle(this); }
};

class EventHandler
{
    void handle( const SmartEvent& event ) {...}
    void handle( const DumbEvent& event ) {...}
};

void main( void )
{
    EventHandler Handler;
    Event* Test = new SmartEvent();
    Test.invokeHandler(Handler);
}

The prevents you from having to write a lot of tests, but still requires
that the invokeHandler() method be duplicated in each event class.

john lilley

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]






Author: Martin D Kealey <martin@kcbbs.gen.nz>
Date: 1997/04/11
Raw View
In article <5iip4q$5bb@netlab.cs.rpi.edu> Benjamin Scherrey wrote:
> I am disappointed in how limited RTTI really is in, what I consider, some
> pretty obvious, commonly required, and easily implemented (I presume)
> functionality.

In general no, it is NOT easily implemented.  It would require a complete
work-over of the linker to match up all the N-tuples of classes and
methods that might involve polymorphic parameters, and generate
N-dimensional despatch vtables that could be quite huge.

> class Event;    // polymorphic class capable of supporting dynamic_cast
> class SmartEvent : public Event { ... };
> class DumbEvent : public Event { ... };
> class ..nextevent ...
>
> class EventHandler
> {
>     void handle( const SmartEvent& event ) {...handle the SmartEvent ...}
>     void handle( const DumbEvent& event ) {...handle the DumbEvent ...}
> };
>
> void main( void )
> {
>     EventHandler Handler;
>     Event* Test = new SmartEvent();
>     Handler.handle( *Test );    // Why can't RTTI resolve this?
> }

Because RTTI only works on "this", which here is (Handler), not (*Test).

Requiring multiple-despatch on all parameters would be prohibitively
expensive in the general case.

> Does anyone have any suggestions for efficient workarounds that will
> allow me to achieve this functionality? I need to handle events without
> knowing their actual inherited types at compiler time.

You need to arrange for a despatch on Event, not (just) on EventHandler.
The easiest way is to add these:

    class EventHandler {
        ...
        void handle( const Event &event ) { event.handle_by( Handler ); }
    };

    class Event {
        ...
        virtual void handle_by( EventHandler& ) const = 0;
    };

In this, handle_by will be despatched by the RTTI, giving the effect you
require.  You may need multiple versions of handle_by if you derive from
EventHandler.

-Martin.
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]

      [ Send an empty e-mail to c++-help@netlab.cs.rpi.edu for info ]
      [ about comp.lang.c++.moderated. First time posters: do this! ]