Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!usc!rpi!batcomputer!cornell!rochester!kodak!islsun!cok From: cok@islsun.Kodak.COM (David Cok) Newsgroups: comp.lang.c++ Subject: Re: typesafe downward casting and contravariance Message-ID: <1991Apr9.165844.11268@kodak.kodak.com> Date: 9 Apr 91 16:58:44 GMT References: <9104091317.AA16916@ucbvax.Berkeley.EDU> Sender: cok@Kodak.COM Organization: Eastman Kodak Co., Rochester, NY Lines: 72 In article <9104091317.AA16916@ucbvax.Berkeley.EDU> schweitz@lexvmc.vnet.ibm.com ("Eric Schweitz") writes: > ..... > > I'm not sure I agree with the idea that contravariance on the > function's return type would make code easier to code, debug, etc. > > I think that if contravariance were allowed, it would make certain things > harder to read. I seems desirable to be able to take an expression one token > at a time to analyze it. > > Here's what I mean by "harder to read." Let's assume that the function > sin() is contravariant... > > > int sin (int); > float sin (float); > complex sin (complex); > > // implementation of sin's... > > float f, g; > int i, j; > The case you give is complicated by the automatic conversions among numeric types. It isn't even proposed by me as something allowed under "contravariance on function return type", which sticks with derived classes returning X*, base classes returning Y*, and X being inherited from Y. The case you have, assuming everything is user defined rather than numeric types, is simple overloading, already present in C++, and succumbs to the rules for overload resolution -- the context of the function call is ignored, only the parameter types are used: > i = sin (j); // OK. uses int sin(int) > f = sin (g); // OK. uses float sin(float) > i = 1 / sin (g); // Which one here? > // (let the compiler decide?) > // (What if these are user-defined classes? > // How would these be promoted/demoted?) g is a float, so use float sin(float) > i = f / sin (g); // or here? same thing here > f = sin (i) / g; // or here? i is an int so use int sin(int) > > complex c; > > c = sin (i) * sin (f) / sin (j) + sin (g); // what does this mean? Straightforward overloading resolution would resolve this too. > > What I mean by contravariance is this: class Base { ... virtual Base* clone(); }; class Derived { ... virtual Derived* clone(); // ^^^^^^^^ C++ currently requires this to be a Base* }; I have a previous post on implementation which I'll send by e-mail to any interested person. David R. Cok Eastman Kodak Company -- Imaging Science Lab cok@Kodak.COM