From: maxtal@extro.ucc.su.OZ.AU (John MAX Skaller)
Subject: Re: run-time type checking (was: Re: Covariant Types in Derived Classes)
Organization: MAXTAL P/L C/- University Computing Centre, Sydney
Date: Sat, 25 Jul 1992 17:42:52 GMT

In article <1992Jul25.022147.24152@lucid.com> jss@lucid.com (Jerry Schwarz) writes:
>
>Here is a typical example of my use of downcasting. Downcasting
>is not essential in this example, but I think it makes the design
>cleaner.

	Perhaps:
	a) stream design is flawed (I happen to think this anyway)
	b) where you use the downcast something else would be
	even better.
>
>I want to define an "indent stream" derived from ostream.
>An indent stream contains an indentation level.  

	You would pick streams, which I never use :-)
	But the problem seems to be well specified :-)
>
>class indentstream : public ostream {
>   public:
>    int level ;  // Public only to keep example short.
>    indentstream(streambuf* sb) : ostream(sb), level(0) { }
>} ;
>
>The level is used by a manipulator.
>
>ostream& newline(ostream& os) {
>    indentstream* is = CAST<indentstream*>os ;  // notation suggestive
>    os.put(\n) ;
>    if ( is ) {
>        for ( int n = 0 ; n < is->level ; ++n ) is.put('\t') ;
>    }
>    os.flush() ;
>}
>
>Typical uses look like
>
>     indentstream myout(...) ;
>     ...
>     myout.level++ ;
>     // x and y inserters do not have to understand indentation as long
>     // as they put everything on a single line.
>     myout << x << newline << y << newline ;
>     myout.level--
>
>This class isn't perfect, but I hope you get the idea.  More elaborate
>methods can be devised that put the newline detection in the
>streambuf and avoid newline.  These also require downcasting so
>that you can be sure the streambuf is the right type before you tell
>it to change level.

	I cant comment for sure on this, I dont have enough experience
with streams. 

	Perhaps streams have to regarded as a foreign interface,
in which case downcasting might be ok.

	Perhaps streams are badly designed (the flaw is in them, not
	your code).

	And perhaps the fact that you are using a downcast indicates
	that you are cheating the system:

I get one of your streams (but I only know it is an ordinary stream).
I write out a file, then read it back in and ---oh, where
did those tabs come from---there's a BUG in the stream package!

Mm, is there, I say, and look at the class semantics
(I read the source code). No, I say, there is NO WAY that
this can happen, there is NO virtual function that would allow
that freedom.

You see this is an example then of how you could do ANYTHING to
something I thought was an implementation fo a stream,
you have invalidated the semantics by downcasting.

>indentstream can be done without derivation and without downcasting by use
>of the iword facility of streams, but that feature of streams is generally
>regarded as baroque and unappealing.  

	And I checked this out and found iword was NOT being fiddled!


>It was included in the stream
>interface precisely because safe downcasting wasn't available.  

	Perhaps it was provided because ANY casting is bad news :-)

>People frequently just go ahead and use an unsafe cast in "newline"
>(or its equivalent).  
>   -- Jerry Schwarz

Your example may be a valid use of downcasting, I'm sorry that
I just dont know enough about streams to argue it.

-- 
;----------------------------------------------------------------------
        JOHN (MAX) SKALLER,         maxtal@extro.ucc.su.oz.au
	Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------