From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Exception Specifications
Organization: Computer Science, University of Melbourne, Australia
Date: Thu, 1 Oct 1992 05:52:16 GMT

sakkinen@jyu.fi (Markku Sakkinen) writes:

>I am afraid that distinguishing exceptions only by the type of the
>'throw' expression is mostly overkill instead of improvement.
>Suppose for instance that you have 20 distinct exceptions,
>which only need to pass an integer's worth of information
>to their handlers (or perhaps no data at all).
>You have to declare a class for each of them.

Is this so difficult?

	class MyException : Exception {};

	struct MyIntException : Exception {
	    int value;
	    MyIntException(int value_) : value(value_) {}
	};

The amount of typing required does not seem to be excessive, IMHO.

>John Skaller has remarked that the exception handling principle
>requires run-time type information in the implementation,
>a thing against which Bjarne Stroustrup has so steadfastly fought
>all these years.  (Of course this does not necessarily mean that
>the information would be available to the lowly programmers
>to misuse.)

The run-time type information need only be supplied for objects which are
actually thrown, not for all objects.

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

One possible implementation is as follows: for each class that may be thrown,
store the name of the class, together with pointers to all the classes it
is derived from (if any):

	struct __Type {
		const char *type_name;
		int num_base_classes;	  // will be >1 for multiple inheritance
		__Type *base_classes[1];  // we're using the "struct hack" for
					  // efficiency :-)
	};

So everytime we see a throw(x) statement, where x is an object of class X,
we generate the type info for X and all it's base classes, and store these in
global constants __type_info_for_class_X etc.

When an exception is thrown, we need to store both the object thrown and also
it's type info:

	void* __exception_object;	// pointer to the object thrown
	__Type* __exception_type;	// run-time type info

The code generated for the throw statement itself looks like:
	__exception_object = new X(x);
	__exception_type   = &__type_info_for_class_X;
	unwind_stack();

Then the code generated for a statement like
	catch(Matherr mm) { ... }
will look like
	if (__matches_type("Matherr", __exception_type)) {
	    Matherr& mm = *(Matherr *)__exception_object;
	    ...
	}
where __matches_type just does string comparison on the type names:

	int __matches_type(const char *type_name, Type *type) {

	    // does it match the class name?
	    if (strcmp(type_name, type->type_name) == 0)
		return TRUE;

	    // does it match with any of the parent classes?
	    for (int i = 0; i < type->num_base_classes)
		if (__matches_type(type_name, type->base_classes[i])
		    return TRUE;

	    // otherwise, no match found
	    return FALSE;
	}

Have I confused you enough already?
Anyway, what I was trying to point out was that it really isn't that
complicated: exception handling only requires run-time type info for objects
that are actually throw, and run-time type identification can just involve
simple string comparisons.

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.std.c++