Topic: Type of the exception object being thrown


Author: tedlaw@vnet.ibm.com ()
Date: Wed, 8 Jun 1994 13:27:48 GMT
Raw View
In <mikey.91.00139D8E@mcs.com>, Mike Young (mikey@mcs.com) wrote:

> The simple answer is "NO." invalidargument is not polymorphic. Only
> polymorphic objects work with RTTI. Classes are polymorphic is they have
> virtual functions somewhere in their heirarchy.

But it is polymorphic!  The destructors of both xmsg and invalidargument
are virtual.  And I can always make it polymorphic by adding virtual
methods.  The question is "what is the type of the exception object
being thrown?"

Ted Law




Author: mikey@mcs.com (Mike Young)
Date: Wed, 8 Jun 1994 22:14:35
Raw View
In article <Cr2yqC.qF8@hawnews.watson.ibm.com> tedlaw@vnet.ibm.com () writes:

>But it is polymorphic!  The destructors of both xmsg and invalidargument
>are virtual.

Ohh! And so they are. :)

> The question is "what is the type of the exception object
>being thrown?"

ARM 15.2 says "a temporary object of the static type of the operand to
throw..." I think this says a class invalidargument is thrown in your example.
ARM 15.4, case [2] says your catch(xmsg &) will receive a reference to the
temporary invalidargument created in the preceding paragraph.

Together, they say that invalidargument is initialized, and the handler
receives a reference to it.

---------------

Dumb question: why are you doing a dynamic cast in the handler? An explicit
catch(invalidargument &) would be better in many ways. For one, it obviates
the need for a definitive answer to this question.

Mike.




Author: tedlaw@vnet.ibm.com ()
Date: Thu, 9 Jun 1994 14:25:27 GMT
Raw View
In <mikey.96.00163EE7@mcs.com>, Mike Young (mikey@mcs.com) wrote:
> ARM 15.2 says "a temporary object of the static type of the operand to
> throw..." I think this says a class invalidargument is thrown in your
> example.

No, in the throw operand, the static type of "this" is pointer to xmsg, the
static type of "*this" is therefore xmsg.  Since the type of the temporary
exception object is now xmsg, it should not be possible to do the
dynamic cast in the handler, according to the draft.

Consider the fact that my example shows that the ANSI C++ library
exception classes use exception handling incorrectly, or at least in a
misleading way, according to the current draft, and the fact that you
yourself also think that the exception object should have the dynamic
type of the throw operand.  I would say it is very easy for a lot of
programmers, who may not be aware of all the fine details of the
language standard, to write incorrect code.  It's just not what people
expect.

Given that RTTI is already part of the language, it should not be
difficult to implement the dynamic type semantics.


> Dumb question: why are you doing a dynamic cast in the handler? An explicit
> catch(invalidargument &) would be better in many ways. For one, it obviates
> the need for a definitive answer to this question.

That's just to illustrate the point.  Furthermore, it is useful in real
life too, because there are times when the programmer wants to be able to
catch all the exceptions under a common base exception class.

Ted Law




Author: haubert@ed8200.ped.pto.ford.com (Phil Haubert)
Date: Thu, 9 Jun 1994 21:36:12 GMT
Raw View
tedlaw@vnet.ibm.com wrote:
: In <mikey.96.00163EE7@mcs.com>, Mike Young (mikey@mcs.com) wrote:
: > ARM 15.2 says "a temporary object of the static type of the operand to
: > throw..." I think this says a class invalidargument is thrown in your
: > example.

: No, in the throw operand, the static type of "this" is pointer to xmsg, the
: static type of "*this" is therefore xmsg.  Since the type of the temporary
: exception object is now xmsg, it should not be possible to do the
: dynamic cast in the handler, according to the draft.

  Correct.  There is a paper by Stroustrup that explains the mechanism
pretty well.

  In order to get polymorphic behavior, an object needs to be
passed by reference; however, when an exception is raised the
object needs to be 'passed' by value:

  try {

    int i = 5;          // put the value '5' on the stack
    throw i;            // make a copy of i (as an int)
                        // remove i from stack
                        // encode somehow that an int is being thrown
                        // at this point it is unknown if the exception
                        // will be caught as reference or value.

  } catch (int& j) {    // this is a reference to the copy of i

    cout << j << "\n";

  }                     // now destroy the value j is bound to


: Given that RTTI is already part of the language, it should not be
: difficult to implement the dynamic type semantics.

  What is caught depends only on the type that is explicitly thrown,
RTTI does not come into play.

(you could make your example work by using covariant return types,
but that is really beside the point)

-phil




Author: tedlaw@vnet.ibm.com ()
Date: Tue, 7 Jun 1994 16:11:35 GMT
Raw View
Consider the following example:

    class xmsg {
      public:
 virtual ~xmsg();
 void raise() {
     throw *this; // The static type of the operand of throw
 }   // is xmsg.
 ...
    };

    class invalidargument : public xmsg {
      public:
 virtual ~invalidargument();
 ...
    };

    void f()
    {
 if ( ... ) {
     invalidargument ex;
     ex.raise();
 }
    }

    main()
    {
 try { f(); }
 catch( xmsg& ex ) {
     invalidargument* i = dynamic_cast<invalidargument*>(&ex);
     // Will this cast work?
 }
    }


Section 15.2 paragraph 3 of the Jan '94 ANSI C++ draft says:
    "A throw-expression initializes a temporary object of the static type
             ^^^^^^
    of the operand of throw and uses that temporary to initialize the
    appropriately-typed variable named in the handler."

It appears that the draft says that the type of the exception object
being thrown should be of type "xmsg", rather than "invalidargument".
Consequently, I should not be able to dynamic_cast as shown.  Is that
the correct interpretation of the draft, or am I missing something?

If it is meant to throw an object of type "xmsg", then what is the rationale?
If it is meant to throw an object of type "invalidargument", then the
wording is not clear enough.

Please note that the example is based on the exception classes
in the proposed standard C++ library.

Ted Law




Author: mikey@mcs.com (Mike Young)
Date: Tue, 7 Jun 1994 19:36:47
Raw View
In article <Cr1BnB.6CsG@hawnews.watson.ibm.com> tedlaw@vnet.ibm.com () writes:
>From: tedlaw@vnet.ibm.com ()
>Subject: Type of the exception object being thrown
>Date: Tue, 7 Jun 1994 16:11:35 GMT


>Consider the following example:

>    class xmsg {
>      public:
>        virtual ~xmsg();
>        void raise() {
>            throw *this;        // The static type of the operand of throw
>        }                       // is xmsg.
>        ...
>    };

>    class invalidargument : public xmsg {
>      public:
>        virtual ~invalidargument();
>        ...
>    };

>    void f()
>    {
>        if ( ... ) {
>            invalidargument     ex;
>            ex.raise();
>        }
>    }

>    main()
>    {
>        try { f(); }
>        catch( xmsg& ex ) {
>            invalidargument*    i = dynamic_cast<invalidargument*>(&ex);
>            // Will this cast work?
>        }
>    }

The simple answer is "NO." invalidargument is not polymorphic. Only
polymorphic objects work with RTTI. Classes are polymorphic is they have
virtual functions somewhere in their heirarchy.

Mike.