Path: utzoo!utgpu!news-server.csri.toronto.edu!rpi!usc!cs.utexas.edu!devnull!kelley@mpd.tandem.com From: kelley@mpd.tandem.com (Michael Kelley) Newsgroups: comp.lang.c++ Subject: Re: typeof() and virtuals and overloading, oh my! Message-ID: <162@devnull.mpd.tandem.com> Date: 2 Apr 91 17:34:22 GMT References: <27F77834.16D6@tct.com> <27EF838D.4115@tct.uucp> <19093@milton.u.washington.edu> <157@devnull.mpd.tandem.com> Sender: news@devnull.mpd.tandem.com Lines: 132 In article <27F77834.16D6@tct.com>, chip@tct.com (Chip Salzenberg) writes: > According to kelley@mpd.tandem.com (Michael Kelley): > > > >Is it realistic to completely decouple the language features from supporting > >libraries? Not here, I think. > > There is no useful distinction to be made between a language feature > and a required library function. Consider that ANSI C permits the > compiler to recognize standard functions and treat them specially, > such as by expanding them inline. After all, if the language system > executes a program correctly, do we care if it uses a library routine > or a compiler feature for function X? I think not. So the issue of > language vs. library is irrelevant to this discussion. > Yes, Chip, there is a distinction. If it's in the language, it (should be/is) portable. If it's not, you can only hope it's portable. Again, bare in mind that I'm NOT arguing to put every feature known to mankind in the language. I like it that C++ is as powerful as it is, yet is still pretty lean and mean. > >I'll go out on a limb and argue that in order to retrieve/activate/thaw > >an object, there MUST be a typeof() defined within the language in order > >to store/pacify/freeze *any* object and its type. > > Sorry; typeof() is neither necessary nor sufficient. > > Not necessary: because a virtual freeze_on() function for each type > can be written. It's a bit of a pain, yes, but it can be done. True, provided *you* implement the class. What happens when you get a class library from vendor X, that doesn't have a pure virtual freeze_on(), much less any implementation for freezing/thawing? Just write those objects off as "forever temporal", rather than peristable. With persistance, distribution over a network is made vastly easier than it is now--and for us (and many others, I believe) the ability to distribute is a requirement. > > Not sufficient: because a simple_minded freeze_on() function that > iterates across member variables cannot deal intelligently with > pointers and references, especially for recursive data structures. > Rather than tightening up the language, as is done with one OODBMS I've seen, I'd like to write static encoders/decoders for my class variables, and let "someone else" who understands hierarchy call them as needed. Since the hierarchy information exists in the header files, in seems natural for the compiler to give "someone else" the information. The typeof() I refer to would be used to access this information, make appropriate encoding/decoding call(s), tag the output when encoding, and compare tags when decoding. If it's not part of the language, then it *must* be done through a virtual function, using a common base class -- not viable if we hope to use libraries written outside of our companies. I did say later that conversion can't be done in the language because of pointers, which you did not see relates to your previous point. Oh well. > >I think at a minimum, we'd need a special constructor (defined as part > >of the language), which just sets up virtual tables, and then calls a > >conversion routine to map "neutralized" data into some architecture-specific > >format. > > Nope. Again because of the possibility of recursive data structures > and other tricks, thaw_from() *cannot* be written automatically, > unless the structures to be frozen and thawed are greatly restricted. > Given that fact, it's up to you, the programmer, to use whatever > convention suits you. Perhaps a one-argument constructor that takes > an "istream &" will do. Again, I'm not arguing for generated conversion. And yes, an istream&, or an XDR*, will do just fine -- for me, for you, for everyone who's ever wrestled with persistance. But if we don't all do it the same way, we're not going to be able to leverage off of each other's work. We'll have a forest of objects that can't talk to each other. > > >As an aside, I don't believe it's possible to make conversion a > >part of the language (witness pointers and the like). But surely we > >could agree on conversion routine names a little-better-than-brain-dead > >linker would know about so that a *standard* library could [de]neutralize > >*any* object, independent of it's subclasses? > > The flaw in this plan is evident in the next paragraph: > > >In case you're wondering, we use a filter to sweep through object modules... > >No macros, no nothing, just as long as our superclass is an ancestor ... > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > > With a common ancestor, all things are possible. The C++ language, > however, is based on a type forest, not a type tree; common ancestors > are the exception, not the rule. > Exactly. The operative phrase was "just as long as". It works *only* because we have a common base class, and I don't like that it has to be that way *because* it is the exception. And I can't see any way to make it work for a forest without help from the language. As an aside, I'm well aware that there's a serious problem with class name clashes. > >Now as I remember, the required "feature" is called dispatching ... > > My comment about "B::foo(B&)" and "D::foo(D&)" not being the same > function is irrelevant to issues of dynamic dispatching. It doesn't > matter _how_ you decide to execute "x.foo()". B::foo() and D:foo() > implement different functions, and thus should be either non-virtual > or distinctly named. Huh? I was addressing the invocation of x.foo(y), in keeping with the prototypes you put down. What matters is that to invoke the right "x.foo()", I don't have to know what type "x" is; but, to invoke the "x.foo(y)" I want, *I've* got to tell the compiler what type "y" really refers to -- the compiler will make a call based on *declared* type otherwise. Maybe I have it all wrong, but I think this is exactly what dispatching is all about. Again, I realize this may be an intractable problem within C++, but to write off requests for such functionality as evidence of bad design is a serious mistake. I'm an unabashed C++ fan, but am not so rabid to reject anything that can't be done using the language as it is today. Some would say "you should use Objective-C or Smalltalk", but for my work, the advantage still goes to C++. Mike Kelley Tandem Computers, Austin, TX kelley@mpd.tandem.com (512) 244-8830 / Fax (512) 244-8247