dfoster@jarthur.Claremont.EDU (Derek R. Foster) (03/11/91)
I have heard a few references lately to the possibility of adding to c++ an overloadable operator dot. I have a few questions about this: 1) Is the committee seriously considering this right now, or is this just a suggestion? If they are considering it, what are the chances of it passing? 2) If this suggestion is actually used, what is the syntax to invoke the normal (un-overloaded) dot operator? Thanks for any information! Derek Riippa Foster
horstman@mathcs.sjsu.edu (Cay Horstmann) (03/11/91)
In article <11152@jarthur.Claremont.EDU> dfoster@jarthur.Claremont.EDU (Derek R. Foster) writes: >I have heard a few references lately to the possibility of adding to c++ >an overloadable operator dot. I have a few questions about this: > >1) Is the committee seriously considering this right now, or is this just > a suggestion? If they are considering it, what are the chances of it > passing? No idea... >2) If this suggestion is actually used, what is the syntax to invoke > the normal (un-overloaded) dot operator? > I guess one could always recover the original meaning by writing (&x)->m or this->m. Note that the -> applies to a pointer and hence cannot be redefined. By redefining operator& (unary), the first method may no longer work. In that case, the actual class members could only be used inside other member functions. Even if no member functions can be launched explicitly (because x.f() no longer means to call X::f() on x), some member functions can still be activated through constructors, destructors, overloaded operators and virtual functions. Inside those member functions, members can be accessed as this->m or simply m. Note that only the members of "this" can be accessed like that, not the members of any other object of the same class. What are the reasons AGAINST allowing overloading operator.? Cay
jimad@microsoft.UUCP (Jim ADCOCK) (03/13/91)
In article <11152@jarthur.Claremont.EDU> dfoster@jarthur.Claremont.EDU (Derek R. Foster) writes: |I have heard a few references lately to the possibility of adding to c++ |an overloadable operator dot. I have a few questions about this: | |1) Is the committee seriously considering this right now, or is this just | a suggestion? If they are considering it, what are the chances of it | passing? I wrote this up as a formal request for review some months ago. Bjarne wrote me last week saying that the idea was still under consideration, and that he likes the idea. How seriously anyone else takes the idea I cannot say. I am encourage by the number of people finding good uses for it recently. |2) If this suggestion is actually used, what is the syntax to invoke | the normal (un-overloaded) dot operator? Operator dot works very similarly to operator point, as a starting point. Like the other overloaded operators, operator dot isn't ever implicitly invoked -- if you don't explicitly type a dot, you don't get an invocation of operator dot. Smart reference classes, like smart pointer classes, are typically pretty simple things. Thus, the easiest way to keep from invoking operator dot when you don't want it [during the construction of your smart reference class] is simply to specify the required members without adornment -- which gives you the standard implicit "this->" prefix. Other "tricks" to avoid "accidentally" getting the overloaded operator dot include implementing some of your smart reference class in a private superclass, and only introduce the operator dot in the subclass, or perhaps doing a (&smartRef)->doSomething();
steve@taumet.com (Stephen Clamage) (03/17/91)
dfoster@jarthur.Claremont.EDU (Derek R. Foster) writes: >I have heard a few references lately to the possibility of adding to c++ >an overloadable operator dot. I have a few questions about this: >1) Is the committee seriously considering this right now, or is this just > a suggestion? If they are considering it, what are the chances of it > passing? >2) If this suggestion is actually used, what is the syntax to invoke > the normal (un-overloaded) dot operator? The ANSI C++ Committee (X3J16) met from 11-15 March, and the issue of overloading the dot operator was discussed. The working group responsible for evaluating extensions to the language presented a summary of their deliberations, and concluded that the issue requires more study. For any suggested addition or change, an important set of questions: Q1. Will any currently-legal programs be affected? Q2. What current functionality will be lost? Q3. What functionality will be added to the language which is not now conveniently available? (What problem does this solve?) Q4. Do the benefits in Q3 make up for the costs in Q1 and Q2? (This is not a formal Committee procedure, but just some things which need to be considered.) The working group said it had not reached a conclusion on Q3 in particular. If adopted, operator dot would probably be analogous to operator arrow. It would have to return a class or reference to a class on which either operator dot was defined, or which had a member corresponding to the name on the right side of the original dot. Given this, there would be no way to use the ordinary dot on a class with operator dot, just as there is no way to use the ordinary arrow on a class with an operator arrow. In particular, you would not define both operator dot and operator arrow for the same class. The result would be unmanageable. Defining either affects the normal guarantee that given class C { ... public: int m; ... } c, *pc; then (&c)->m c.m pc->m (*pc).m are all equivalent. p->m and (*p).m are equivalent. -- Steve Clamage, TauMetric Corp, steve@taumet.com
horstman@mathcs.sjsu.edu (Cay Horstmann) (03/18/91)
In article <624@taumet.com> steve@taumet.com (Stephen Clamage) writes: > >In particular, you would not define both operator dot and operator arrow >for the same class. The result would be unmanageable. I don't think that is true at all. First of all, inside a MEMBER FUNCTION of X (a class with both operators . and -> overloaded), you could still access the members. That should be sufficient for implementing such very specialized classes. Furthermore, if X::operator& is not redefined, member access is still possible through (&x)->m, since -> cannot be overloaded for the pointer type X*. I am NOT saying that operator. should necessarily be overloadable just because it can be done. Just that the most common argument ("it would be a mess to access members") doesn't hold water. Just out of curiosity: has the working group identified any code that would break if operator. overloading was permitted? (Stephen cited that as one important task of the working group.) The most important question is of course: Does it solve any problems? Recently it was generally agreed that it would be useful for defining an access class which can be both an lvalue and an rvalue. Is anyone aware of another use for it? Cay
dsr@mir.mitre.org (Douglas S. Rand) (03/18/91)
In article <1991Mar17.184122.717@mathcs.sjsu.edu>, horstman@mathcs.sjsu.edu (Cay Horstmann) writes: > In article <624@taumet.com> steve@taumet.com (Stephen Clamage) writes: > > > >In particular, you would not define both operator dot and operator arrow > >for the same class. The result would be unmanageable. > > I don't think that is true at all. First of all, inside a MEMBER FUNCTION > of X (a class with both operators . and -> overloaded), you could still access > the members. That should be sufficient for implementing such very specialized > classes. Furthermore, if X::operator& is not redefined, member access is > still possible through (&x)->m, since -> cannot be overloaded for the pointer > type X*. > > I am NOT saying that operator. should necessarily be overloadable just because > it can be done. Just that the most common argument ("it would be a mess to > access members") doesn't hold water. Just out of curiosity: has the working > group identified any code that would break if operator. overloading was > permitted? (Stephen cited that as one important task of the working group.) > > The most important question is of course: Does it solve any problems? Recently > it was generally agreed that it would be useful for defining an access class > which can be both an lvalue and an rvalue. Is anyone aware of another use for > it? > > Cay Yes, it would allow the creating of true persistent objects where there was little, if any, programmer overhead of dealing with them. To explain; the persistent object implementations I've done all require me to explicitly force the loading of an object either at construction time or before the first access. Lazy loading of objects is then very difficult and for a large system one definitely wants to load objects on a "as needed" basis. When a programmer modifies an object one needs to update a writeback list or directly store the instance. With overloaded "." one can check for the load state of the persistent instance on access and automatically load the instance. This is much cleaner. With overloaded "." as an lvalue one can increment writeback lists automatically or store through to the database. -- Douglas S. Rand Internet: <dsrand@mitre.org> Snail: MITRE, Burlington Road, Bedford, MA Disclaimer: MITRE might agree with me - then again... Amateur Radio: KC1KJ
jbuck@galileo.berkeley.edu (Joe Buck) (03/21/91)
In article <624@taumet.com>, steve@taumet.com (Stephen Clamage) writes: > The ANSI C++ Committee (X3J16) met from 11-15 March, and the issue of > overloading the dot operator was discussed. The working group > responsible for evaluating extensions to the language presented a summary > of their deliberations, and concluded that the issue requires more study. > For any suggested addition or change, an important set of questions: > Q1. Will any currently-legal programs be affected? > Q2. What current functionality will be lost? No and no. The change has no effect on any working program (but I suppose you knew that and are just asking the "standard set of questions") since existing programs call "operator ." a syntax error. |> Q3. What functionality will be added to the language which is not now |> conveniently available? (What problem does this solve?) The new functionality is the ability to have "smart references". The semantics parallels the semantics for "smart pointers" obtained by overloading operator -> and should have the same restrictions. The new text would read "Class member access using . primary-expression . primary-expression is considered a unary operator. An expression x.m is interpreted as (x.operator.()).m for a class object x (here the first "." is the builtin "." -- perhaps I should write ((&x)->operator.()).m to be unambiguous). It follows that operator.() must return either a reference to a class or an object of, or reference to a class for which operator.() is defined. operator.() must be a nonstatic member function." |> Q4. Do the benefits in Q3 make up for the costs in Q1 and Q2? Since there are no costs in Q1 and Q2, obviously. Of course, there is a cost for compiler writers, and a cost for the standards committee. |> If adopted, operator dot would probably be analogous to operator arrow. |> It would have to return a class or reference to a class on which either |> operator dot was defined, or which had a member corresponding to the name |> on the right side of the original dot. Given this, there would be no |> way to use the ordinary dot on a class with operator dot, just as there |> is no way to use the ordinary arrow on a class with an operator arrow. I agree. The wording should be the same as what appears in 13.4.6 of the ARM, except that where "pointer" appears "reference" should be substituted. |> In particular, you would not define both operator dot and operator arrow |> for the same class. The result would be unmanageable. I agree that in practice, an object will either behave as a smart reference or a smart pointer and not both, but I don't think the compiler should enforce this restriction. It's still possible for an object to refer to its own members within member functions without mentioning either the . or -> operator. When teaching someone the language, though, I'd discourage, STRONGLY, redefining both for the same object. Smart references will make it easier to write garbage collectors (though the C-compatible array semantics can leave holes in the scheme). -- Joe Buck jbuck@galileo.berkeley.edu {uunet,ucbvax}!galileo.berkeley.edu!jbuck
wmm@world.std.com (William M Miller) (03/21/91)
jbuck@galileo.berkeley.edu (Joe Buck) writes: > |> Q3. What functionality will be added to the language which is not now > |> conveniently available? (What problem does this solve?) > > The new functionality is the ability to have "smart references". The > semantics parallels the semantics for "smart pointers" obtained by overloading > operator -> and should have the same restrictions. That doesn't answer the question -- all you've done is to give the new feature a name. The real issue is whether the technique solves any major problems that can only be addressed awkwardly or not at all in the existing language. In other words, give some specific applications that demonstrate that "smart references" aren't just another of the hundreds of nifty ideas floating around that are cute and interesting but don't really expand the power of the language to address real-world problems. To give an example, exception handling was added to the language because there simply is no way without it safely to employ a non-local goto to terminate a failing operation. As a negative example, generalized overriding (aka "renaming") was a very attractive feature that was rejected in large measure because a fairly straightforward programming technique was discovered that solved the problem to which the extension was originally addressed. For instance, one proposed use of operator.() given in this newsgroup a short while ago was to implement auxiliary classes used as the return type of operator[](). It's not apparent to me, at least, that defining operator.() in such a class is sufficiently superior to the alternate technique of coding any necessary forwarding functions directly into the auxiliary class. In fact, addressing the original problem (detecting the difference between lvalue and rvalue use of the result of operator[]()) will require coding some glue functions into the intermediate class to allow the desired separation between lvalue and rvalue operations, so the relative value of operator.() for such an application is reduced even further. > |> Q4. Do the benefits in Q3 make up for the costs in Q1 and Q2? > > Since there are no costs in Q1 and Q2, obviously. Of course, there is > a cost for compiler writers, and a cost for the standards committee. Actually, those aren't the only costs; some of the conceptual unity of the language will be lost if operator.() is adopted. For one thing, it is currently absolutely guaranteed that, if you see "foo.bar" in a program, "bar" is a member of the class of which "foo" is an object. That guarantee will be broken if operator.() is adopted; you'll have to look at the definition of the class of "foo" in order to know what the expression means. Perhaps more important is the fact that a fundamental identity in the language will be broken. In at least the form of the proposal I have seen (although there are others, I believe), "p->m" and "(*p).m" are no longer equivalent by definition if "p" is a pointer to a class in which operator.() is defined. This is the only case in which a fundamental C identity is broken for a non-class type (a pointer to a class object is a built-in type, not a user-defined type). These are non-trivial costs, at least to me, even if they can't be evaluated in terms of number of lines of code requiring modification. Don't get me wrong, here; I'm not fundamentally or irrevocably opposed to the idea of operator.(), I just want to be sure that there are good, solid reasons for adopting it beyond "it sure is a nifty idea." > Smart references will make it easier to write garbage collectors (though > the C-compatible array semantics can leave holes in the scheme). This sounds promising, like what I was asking for above. What do smart references buy that smart pointers don't with respect to garbage collection? -- William M. Miller, Glockenspiel, Ltd. wmm@world.std.com
steve@taumet.com (Stephen Clamage) (03/22/91)
jbuck@galileo.berkeley.edu (Joe Buck) writes: >In article <624@taumet.com>, steve@taumet.com (Stephen Clamage) writes: >|> Q3. What functionality will be added to the language which is not now >|> conveniently available? (What problem does this solve?) >The new functionality is the ability to have "smart references". The >semantics parallels the semantics for "smart pointers" obtained by overloading >operator -> and should have the same restrictions. Aha! But is this in fact "new functionality"? What is the difference between a smart pointer and a smart reference in terms of the kinds of programming you can do and the code you have to write to do it? It was not clear to the group looking into the issue that there was a significant difference, or that it justified the added complexity in the language. On the other hand, it was not clear that the idea should be rejected either. That is why they recommended further study. (As an aside, I am not part of the group investigating this issue, nor do I have strong feelings about it either way.) -- Steve Clamage, TauMetric Corp, steve@taumet.com
jimad@microsoft.UUCP (Jim ADCOCK) (03/22/91)
In article <1991Mar17.184122.717@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes: |The most important question is of course: Does it solve any problems? Recently |it was generally agreed that it would be useful for defining an access class |which can be both an lvalue and an rvalue. Is anyone aware of another use for |it? Overloaded operator dot is for all practical purposes necessary in order to be able to make "smart reference classes" just as today one can make "smart pointer classes." The question then becomes why would one prefer to use "smart reference classes" over "smart pointer classes" ??? [I use the term "smart" here in a very loose sense. By a "smart pointer class" I really mean any class that is implemented to act as if it is a pointer -- whether that class does anything intelligent, or simply forwards all requests to the pointed-at object is immaterial to my discussion. The same holds true for "smart reference classes"] Two situation where "smart reference classes" are clearly preferrable to "smart pointer classes" are: 1) when such an object has to act like a value, and 2) when such an object has to act like a normal object. [A simpler way to say this would be to state that smart reference classes are always preferred to smart pointer classes -- except when you're trying to make a pointer class -- but that sounds like a circular argument.] Lets see how this might be used. First case is when a smart reference class has to act like a value. Matrices have been a hot topic recently -- let's consider how one would make a reference counted matrices class. Lets call the class that implements the actual storage requirements and reference count of the matrices the ActualMatrix class, and have the smart reference class simply called Matrix -- in order to hide implementation details from the end users. We want to be able to write code like this: Matrix ReadANewMatrix(int row, int col) { Matrix A(row, col); for (int i=0; i<row; ++i) for (int j=0; j<col; ++j) A[i][j] = ReadAValue(); return A; } Remember that Matrix is actually a smart reference class -- when a Matrix is constructed, an ActualMatrix is being created in the background off of heap. The Matrix copy-constructor and assignment simply adjust the reference count in ActualMatrix. [I'll leave the details of when, if ever, separate copies of ActualMatrixes are generated to the discretion of the reader.] If its not obvious to you why you wouldn't want to use a smart pointer implementation instead, consider how such an implementation ought to look in order to mimic pointers: MatrixPtr ReadANewMatrix(int row, int col) { MatrixPtr A = new ActualMatrix(10, 20) for (int i=0; i<row; ++i) for (int j=0; j<col; ++j) (*A)[i][j] = ReadAValue(); return A; } Which doesn't do nearly as good a job of hiding the abstraction. A similar case would be reference counted string classes. The second case where "smart reference classes" are preferred to smart pointer classes is when you want the implementation details to be hidden. If you make a class Foo which delegates a portion or all of its actual work to Bar, do you really want to make it clear that this delegation is being performed, or is the delegation an implementation detail for Foo that should remain hidden? If the implementor of Foo want to hide the delegation [and more than a couple methods are being delegated] then you really need operator dot, so that you can just say: "delegate 'all' these methods to Bar." Consider the case of a named object that's huge, knows its huge, and thus tries to keep its representation on disc most of the time: Class TryToBeDiscResident : public ThingsProtocol { FileName fileName; // where to find the object when *its not* // in memory! Thing* p; // where to find the object when *it is* in // memory! public: Thing& operator.(); .... }; Thing& TryToBeDiscResident::operator.() { if (p == NULL) { p = GoGetThingFrom(fileName); } return *p; } [I'll leave it to the reader to decide when and how Things that TryToBeDiscResident take themselves back out of memory and onto disc.] Note that its possible to create "smart reference classes" today -- even without overloadable operator dot -- and lots of people are creating such smart reference classes -- its just that to do so requires the author to manually write a "trivial" [but annoying] forwarding method for each and every method in the protocol to be forwarded, and afterwards to manually provide software maintanence to keep all those forwarding methods up-to-date. Whereas is overloadable operator dot is supported, not only is it not necessary to manually write all the forwarding methods -- in many situations one could use a standard "smart reference class" template to do "all" the work for you. In summary: I believe overloadable operator dot is *at least* as useful as overloadable operator->, and is necessary if you want to be able to use templates to make smart reference classes.
gintera@fsd.cpsc.ucalgary.ca (Andrew Ginter) (03/23/91)
In article <71437@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: > ... Consider the case of a named object that's huge, >knows its huge, and thus tries to keep its representation on disc most of >the time: > >Class TryToBeDiscResident : public ThingsProtocol >{ > FileName fileName; // where to find the object when *its not* > // in memory! > > Thing* p; // where to find the object when *it is* in > // memory! >public: > Thing& operator.(); > .... >}; > >Thing& TryToBeDiscResident::operator.() >{ > if (p == NULL) > { > p = GoGetThingFrom(fileName); > } > > return *p; > >} > >[I'll leave it to the reader to decide when and how Things that >TryToBeDiscResident take themselves back out of memory and onto disc.] This implementation of an overloaded "dot" operator may be ultimately useful. I'm not arguing that point. A straightforward implementation of such an overloading mechanism however, in the style of existing support for smart pointers, will suffer from the same serious flaws that existing smart pointer support suffers. Taking your example, a programmer may wish to write something which appears perfectly reasonable: int do_stuff (); X.a = do_stuff (); The current C++ language definition does not define the order of evaluation of the assignment expression. If the LHS is evaluated first, the Thing to which X refers is brought into memory (if it wasn't there already) and the emitted code may obtain a pointer to the "a" element in this thing. The intent being that the RHS would then be evaluated and the result assigned to "X.a" through this pointer which was perhaps stored in a processor register across the call to do_stuff. The problem with this expression is that do_stuff may do something which causes the Thing to which X refers to be flushed back to disk. The subsequent assignment through the stored pointer does not update the disk-resident Thing, it updates the memory the Thing used to occupy. This problem and similar problems which arise in smart pointers can be solved by further modifying the language definition to correct these order of evaluation problems. For a detailed discussion of this problem and its solution, see my technical report No. 91/417/01. The report is available as the compressed ".dvi" file DUA3:[ANONYMOUS.PUB.TECH]CPSC-91-417-01-DVI.Z from ucnet.ucalgary.ca. Hard copies can be ordered from the CS dept at (403) 220-6015. Andrew Ginter, 403-220-6320, gintera@cpsc.ucalgary.ca
rfg@NCD.COM (Ron Guilmette) (03/25/91)
In article <1991Mar11.061204.6023@mathcs.sjsu.edu> horstman@mathcs.sjsu.edu (Cay Horstmann) writes: +In article <11152@jarthur.Claremont.EDU> dfoster@jarthur.Claremont.EDU (Derek R. Foster) writes: +>I have heard a few references lately to the possibility of adding to c++ +>an overloadable operator dot. I have a few questions about this: +> +>1) Is the committee seriously considering this right now, or is this just +> a suggestion? If they are considering it, what are the chances of it +> passing? It is being considered seriously by x3j16. +>2) If this suggestion is actually used, what is the syntax to invoke +> the normal (un-overloaded) dot operator? +> +I guess one could always recover the original meaning by writing +(&x)->m or this->m. Note that the -> applies to a pointer and hence +cannot be redefined. In order to understand how this would work, I think that you would have to look at the whole proposal. I'm not sure, but I think that the idea is to allow something like: expression.expression If that is true, then this would be a lot different from the normal way that thinsg work with ".". In particular, you normally have to have the name of a member (or the proper type) to the right of the dot. The thing to the right of the dot cannot be a general expression (as of now). I believe that the "overloadable dot" proposal might change that, but don't quote me. +What are the reasons AGAINST allowing overloading operator.? I have said this over and over again, but either the "overloadable dot" proposal is something radically different from what I think it is or else some people are choosing to ignore some very basic facts. (If it is the latter... well... there would be nothing particularly new about that!) The bare fact of the matter (as I have said many times) is that "." is plainly not an operator (either unary or binary). It is a selector. The C and C++ languages allow the thing on the left of the "." to be an expression (of some struct/class type) but the thing on the right is NOT an expression, rather it must be the name of a member of the thing on the left. In effect, dot acts a bit like the other "scope opener" that we know about in C++, i.e. the colon-colon. These things are plainly NOT operators. People who are just learning the language (as well as experienced users) will just get more and more confused (when trying to read code) if we start to bend the "normal" rules regarding what may and may not be overloaded (or treated like an operator). I have previously noted that allowing overloading for "." makes about as much sense as allowing overloading for "{". In both cases the very idea appears ridiculous, however I actually read a response from one person who said that (maybe) allowing overloading for "{" would be a useful and good thing!!! I guess the bottom line is this. What is your opinion regarding how a language should be designed? Should it be an unbridled, nonsensical and chaotic mismash of random "bright ideas" which seem like they might occasionally have some obscure usefulness, or should there be some rules, some guiding principals, and some *consistancy* in the set of features provided by a language? I feel that the design of C++ ought to have followed the simple (and consistant) rule that overloading would only be allowed for things which really are "operators". Some people don't like to be bound by such trivial concerns as "consistancy" however. Some folks prefer the "everything *including* the kitchen sink" approach to language design. For those people, I have but one question. Why stop with overloading "."? Why not allow overloading for "{" and "}"? What about overloading ":" and/or "::"? Come to think of it... why stop at just the tokens formed from "special characters"? Why not allow overloading of keywords? If you are going to have an unconstrained free-for-all, why not go all the way? -- // Ron ("Shoot From The Hip") Guilmette // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // New motto: If it ain't broke, try using a bigger hammer.
rfg@NCD.COM (Ron Guilmette) (03/25/91)
In article <12193@pasteur.Berkeley.EDU> jbuck@galileo.berkeley.edu (Joe Buck) writes: > >|> Q3. What functionality will be added to the language which is not now >|> conveniently available? (What problem does this solve?) > >The new functionality is the ability to have "smart references". The >semantics parallels the semantics for "smart pointers" obtained by overloading >operator -> and should have the same restrictions. [... stuff deleted ... ] >Smart references will make it easier to write garbage collectors (though >the C-compatible array semantics can leave holes in the scheme). Horse pucky! Prove it! I claim that even if you *had* your so-called "smart references" today, there is absolutely nothing that you could do with them that you could not do just as well using only "smart pointers". I also claim that there is nothing that you could do significantly *easier* with "smart references" than you could with just smart pointers. If you have a counterexample I encourage you to post it and prove me wrong. (Post the code please. Hemming and hawing in flowery prose will not help to make the point either way.) -- // Ron ("Shoot From The Hip") Guilmette // Internet: rfg@ncd.com uucp: ...uunet!lupine!rfg // New motto: If it ain't broke, try using a bigger hammer.
wmm@world.std.com (William M Miller) (03/25/91)
rfg@NCD.COM (Ron Guilmette) writes: > In order to understand how this would work, I think that you would have > to look at the whole proposal. I'm not sure, but I think that the idea > is to allow something like: > > expression.expression > > If that is true, then this would be a lot different from the normal way > that thinsg work with ".". In particular, you normally have to have > the name of a member (or the proper type) to the right of the dot. The > thing to the right of the dot cannot be a general expression (as of now). > I believe that the "overloadable dot" proposal might change that, but > don't quote me. Good advice. The proposal that is most actively under discussion has the same restriction on what follows overloaded "." as the current language places on what follows overloaded "->", i.e., it has to be a member of whatever class the left-hand side eventually resolves to. (Like operator->() might return an object with operator->() defined, operator.() might return an object with operator.() defined; following the chain of results must eventually produce something to which the built-in "->" or "." can be applied.) > The bare fact of the matter (as I have said many times) is that "." is > plainly not an operator (either unary or binary). It is a selector. The counter argument is that, if you can create a user-defined type that acts like a pointer, which you can -- even without operator->(), if you're willing to live only with the unary * notation -- why shouldn't you be able to create a user-defined type that acts like a reference? And if you do, why should the syntax differ from that used with built-in references? And if the syntax is the same, what should you write as an operator in your smart reference class to be invoked when you say "foo.bar"? I agree that "." is _not_ an operator as I think of operators. I just don't have a better suggestion for how to write a smart reference class. (In case anyone is confused by my postings on the subject, which appear to blow both hot and cold on the idea of smart references, I have no insuperable objections to the feature but have not yet been convinced that there is enough of a need to override the minor concerns I have and my desire not to fiddle with the language to add every "bright idea" that comes along.) > should there be some > rules, some guiding principals, There have always been "guiding principals" (Bjarne and crew originally, now X3J16); I think there have generally been guiding _principles_ as well. (Sorry for the "principal/principle" pun, but I couldn't resist. :-) -- William M. Miller, Glockenspiel, Ltd. wmm@world.std.com
gyro@kestrel.edu (Scott Layson) (03/26/91)
In article <4610@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >I claim that even if you *had* your so-called "smart references" today, >there is absolutely nothing that you could do with them that you could >not do just as well using only "smart pointers". > >I also claim that there is nothing that you could do significantly *easier* >with "smart references" than you could with just smart pointers. > >If you have a counterexample I encourage you to post it and prove me wrong. >(Post the code please. Hemming and hawing in flowery prose will not help >to make the point either way.) Here's something I actually tried to do, with encouragement from an experienced C++ programmer, and ran head-on into the absence of overloadable `.'. I wanted to be able to define "active slots" of objects -- sortof like member variables, but with the option of running arbitrary code when the slot was read or written. (This idea was inspired by other object-oriented systems I have used.) So, let's say I have an object `foo', of class `Frob', with a slot `name' of type `symbol'; I want to be able to use the expression `name(foo)' to read the name, and `name(foo) = bar' to write it (there was a reason why I used `name(foo)' rather than `foo.name()', but it doesn't matter here). The way I went about this was to create a class called `_Frob_name' (these declarations were being automatically generated, by the way) such that 1) the implicit conversion from `_Frob_name' to `symbol' (the type of the `name' slot) would run the "read demons", and 2) `_Frob_name::operator=' was overloaded to run the "write demons". The declarations to accomplish this are not hard to generate, but since you ask, they look basically like this: class Frob { // whatever private members public: friend class _Frob_name; friend _Frob_name name(Frob); }; class _Frob_name { Frob _Frob; _Frob_name(Frob f) { _Frob = f; } public: friend name(Frob); operator symbol(); symbol operator=(symbol); }; inline _Frob_name name(Frob f) { return _Frob_name(f); } _Frob_name::operator symbol() { // run "read demons" symbol& val = // however you get a reference to the `name' of _Frob return val; } symbol _Frob_name::operator=(symbol s) { // run "write demons" symbol& val = // however you get a reference to the `name' of _Frob val = s; return s; } The problem, anyhow, is that (supposing `symbol' has a member function `hash') I can't say `name(foo).hash()'. Could I have made this work by using pointers to the intermediate class `_Frob_name' instead of instances thereof? No, because then I couldn't overload `operator='. -- Scott Layson Burson Gyro@Reasoning.COM
jimad@microsoft.UUCP (Jim ADCOCK) (03/26/91)
In article <1991Mar21.032937.16534@world.std.com> wmm@world.std.com (William M Miller) writes: |That doesn't answer the question -- all you've done is to give the new |feature a name. The real issue is whether the technique solves any major |problems that can only be addressed awkwardly or not at all in the existing |language. In other words, give some specific applications that demonstrate |that "smart references" aren't just another of the hundreds of nifty ideas |floating around that are cute and interesting but don't really expand the |power of the language to address real-world problems. I disagree. On the contrary, I believe Joe Buck, myself, and others have repeatedly shown what the problem is. But, when we place all the problems we've found into one category which we label "smart references" some people argue that we're just applying a name to a category we've made up. And then when we show specific short examples of the problem then people argue that the examples we give are academic and give hack work-arounds. Even if it *were* true that people can do things similar to smart references with smart pointers [albeit at the cost of customers having to guess whether to use pointer or dot syntax everywhere] why should it be that throughout the C++ languages people have the choice to either use pointers or references -- -- EXCEPT when it comes to operator overloading? Why not just make the language orthogonal and say that its up to the programmer to decide when its appropriate to use pointers, and when its appropriate to use references? Why in this one obscure case in the language try to mandate some people's preference of pointers over references? Why defend an exceptional case, when it can be easily removed?
dgil@pa.reuter.COM (Dave Gillett) (03/26/91)
In <1991Mar21.032937.16534@world.std.com> wmm@world.std.com (William M Miller) writes: >jbuck@galileo.berkeley.edu (Joe Buck) writes: >> |> Q3. What functionality will be added to the language which is not now >> |> conveniently available? (What problem does this solve?) >That doesn't answer the question -- all you've done is to give the new >feature a name. The real issue is whether the technique solves any major >problems that can only be addressed awkwardly or not at all in the existing >language. In other words, give some specific applications that demonstrate >that "smart references" aren't just another of the hundreds of nifty ideas >floating around that are cute and interesting but don't really expand the >power of the language to address real-world problems. Without the facility to overload operator., one must resort to code like (&f)->thing to get the equivalent, and overload operator->. Without overloading of operator->, we know that this is equivalent to writing f.thing and it would be "really really nice" (i.e. highly desirable) to be able to guarantee to users of a class that this equivalence holds, even if the operators are overloaded. [i.e. I would prefer that for any class where operator-> is overloaded, operator. would be overloaded to preserve this equivalence; leave it up to the user of the class whether they want to use an f or an f*.] Dave
daves@ex.heurikon.com (Dave Scidmore) (03/27/91)
In article <71516@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: > >I disagree. On the contrary, I believe Joe Buck, myself, and others >have repeatedly shown what the problem is.` In following this discussion I have noticed that most of these examples start with the statement "I want to design some set of objects to do X and I want to do this by using langauge feature Y in this way". It do not believe that there is any meaning in showing that given a contrived set of circumstances the language can not meet the needs of your program. To do so is to expect the language to be all things to all people. What is important is whether their is a solution set for your problem, without any contrived conditions or usages of language features, which maps cleanly to your problem. I believe that with some effort a clean approach that does not require modification of the language is possible for every one of the examples given so far. That solution starts with rethinking how you want to achieve the end result and picking an approach that is a good fit with existing language features. >But, when we place all the problems >we've found into one category which we label "smart references" some >people argue that we're just applying a name to a category we've made up. Since "f.thing" and "(&f)->thing are equivilent in a sense smart references already exist. If you think of "f->thing" as being equivelent to "(*f).thing" then it becomes clear why "->" is was originaly made overloadable and "." was not. Since overloading of "*" is allowed how do you overload the implicit "*" in "f->thing" (i.e. (*f).thing). The method chosen was to allow overloading of "->". Since "." has not implicit dereference overloading was not needed. >And then when we show specific short examples of the problem then people >argue that the examples we give are academic and give hack work-arounds. I for one do not think using "(&f)->thing" is a hack workaround. It is quite clear to me what is intended. >Why not just make the language orthogonal and say that its up to the >programmer to decide when its appropriate to use pointers, and when >its appropriate to use references? Why in this one obscure case in the >language try to mandate some people's preference of pointers over references? >Why defend an exceptional case, when it can be easily removed? One reason I have seen given (you must have missed it) is that it alters the syntax of the language in ways that make it hard to predict the outcome. Currently "expression.expression" is not allowed, your change would make it allowable. If this creates side effects then its removal will be far from easy. -- Dave Scidmore, Heurikon Corp. dave.scidmore@heurikon.com
jimad@microsoft.UUCP (Jim ADCOCK) (03/29/91)
In article <1991Mar22.172215.20521@cpsc.ucalgary.ca> gintera@fsd.cpsc.ucalgary.ca (Andrew Ginter) writes: |The current C++ language definition does not define the order of |evaluation of the assignment expression. If the LHS is evaluated |first, the Thing to which X refers is brought into memory (if it |wasn't there already) and the emitted code may obtain a pointer to the |"a" element in this thing. The intent being that the RHS would then |be evaluated and the result assigned to "X.a" through this pointer |which was perhaps stored in a processor register across the call to |do_stuff. | |The problem with this expression is that do_stuff may do something |which causes the Thing to which X refers to be flushed back to disk. |The subsequent assignment through the stored pointer does not update |the disk-resident Thing, it updates the memory the Thing used to |occupy. Like I said, I leave it to the reader to determine when a good time to flush X back to disk. One strategy for when to flush back to disk is to wait till program termination. In which case the overloaded operator dot is being used to implement a deferred load. [See Wirth's comments regards deferred loading in the Oberon System, for example] ---- Again, the problem I see is that when I or others post short, acedemic examples of using operator dot, people attack the examples as being acedemic, whereas if we generalize the use of operator dot and call that generalization "smart references" then people accuse us of applying a name to a "non-problem." Really, the only significant difference between overloaded operator dot and operator-> is the syntax presented to the end user. If ANSI-C++ committee members consider it a "good thing" for end users to have to guess whether to use "." or "->" in any given situation, then overloaded operator-> suffices. However, if the ANSI-C++ committee members consider it a "good thing" that the historical use of "." be maintained when manipulating values, whereas "->" be used when manipulating "pointed-to" things, then the committee members should give us overloaded operator dot so that we can make that distinction -- so that we can use "." when we write classes that act like values, and we can use "->' when we write classes that act like pointers. But, if the committee members no longer consider the distinction between "." and "->" important, then how about removing the distinction completely from the language, and let the compiler distinguish from context which is meant [please note that this is a rhetorical argument :-] I claim the distinction between values and references remains important in C++, as does the distinction between "." and "->" Therefore, the ANSI-C++ committee members ought to give us the necessary tools to write classes using either syntax.
jimad@microsoft.UUCP (Jim ADCOCK) (04/02/91)
In article <1991Mar25.154128.4138@world.std.com> wmm@world.std.com (William M Miller) writes: Newsgroups: comp.lang.c++ Subject: Re: Overloaded operator dot? Summary: Expires: References: <11152@jarthur.Claremont.EDU> <1991Mar11.061204.6023@mathcs.sjsu.edu> <4607@lupine.NCD.COM> <1991Mar25.154128.4138@world.std.com> Sender: Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Followup-To: Distribution: Organization: Microsoft Corp., Redmond WA Keywords: In article <1991Mar25.154128.4138@world.std.com> wmm@world.std.com (William M Miller) writes: |There have always been "guiding principals" (Bjarne and crew originally, now |X3J16); I think there have generally been guiding _principles_ as well. |(Sorry for the "principal/principle" pun, but I couldn't resist. :-) Okay, I'll bite: I claim one of those guiding principles ought to be that whenever we have a chance to 1) change the definition to make the language more orthogonal, removing a special case "wart" WITHOUT negatively impacting existing code, verses 2) leaving the language the same, arguing the change is not worth the effort, that we should "almost always" make that effort. IE the burden of proof ought to be on the supporters of the "wart", not on the people who want to remove the unnecessary special case. It may take a little extra effort to remove these "warts" from existing compilers, but over the lifetime of the language, its going to make 10s of thousands of programmers lives easier. ---- Another second guiding principle ought to be: The ANSI-C++ spec specifies *language* not *implementation.* ---- And "my" third guiding principle would be, the ANSI-C++ specification either calls out *one* behavior for a compiler regards a particular feature, or leaves *all* interpretation of that feature "implementation dependent" BUT DOES NOT specify two contradictory *implementations* either of which [but no other] is acceptible. [IE either agree to agree, or agree to disagree, but *don't* agree to try to lock out future implementations!]
jimad@microsoft.UUCP (Jim ADCOCK) (04/03/91)
In article <4610@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: |Horse pucky! Prove it! What would such a "proof" consist of Ron? I'd post an example using references, you'd post an example using pointers, you'd claim your code is "better" and I'd claim my code is "better." Lets be honest, some people think C++ shouldn't have had references in the first place, but are still fighting a read guard to cripple them now that they're in the C++ language. |I claim that even if you *had* your so-called "smart references" today, |there is absolutely nothing that you could do with them that you could |not do just as well using only "smart pointers". One counter-example to this claim already posted is the example of a ref-counted element of a matrix. Matrix::operator[] needs to return a "smart reference" class because it needs to do reference counting, and it needs to follow value semantics because it in turn needs to have operator[] applied to it in order to get to the individual element. |I also claim that there is nothing that you could do significantly *easier* |with "smart references" than you could with just smart pointers. Show me how you do the reference counted element of a matrix example? Also, I claim "smart pointers" today are frequently used in situations where the "smart pointer" class does not support the full contigency of pointer operations -- but rather can only be used to refer to a single object. Such is not properly a pointer -- it doesn't support pointer operations such as increment, decrement, operator[], etc. If its a "reference counting smart pointer" chances are it doesn't even support assignment of null -- because reference counting smart pointers need to target an actual objec that keeps track of the reference count. So, much of the time "smart pointers" are actually implementing "smart references" today -- but are using inappropriate syntax. Since these people are actually implementing references, why can't they use reference syntax???? |If you have a counterexample I encourage you to post it and prove me wrong. |(Post the code please. Hemming and hawing in flowery prose will not help |to make the point either way.) Again, people have already posted examples of returning an instance of some class from a matrix via operator[]. Such class is naturally a "smart reference" since it in turn needs to follow "value semantics" in order that operator[] can in turn be applied to it. Show me how you solve this problem using "smart pointers" ??? Also, Ron is using a a circular argument. While doing his best to keep people from having compilers that support operator-dot, Ron complains that people don't have good examples of using operator-dot. We haven't exactly had a flood of good examples of using templates or exceptions posted to notes either -- because most people don't have compilers supporting such yet. How about if Ron posts his favorite "smart pointer" code, I'll do my best to convert it to "smart reference" code, and then we'll argue about which is inferior? Again, why are some people so vested in maintaining a minute non-orthogonal wart in the language??? Why not just make the language orthogonal, and say "all operators can be overloaded"??? If some C++ programmers consider overloading operator-dot a "bad" idea -- **** THEN DONT DO IT! **** Why is it necessary to force your prejudices of what constitutes "good programming" onto others?
jimad@microsoft.UUCP (Jim ADCOCK) (04/03/91)
In article <275@heurikon.heurikon.com> daves@ex.heurikon.com (Dave Scidmore) writes: |In following this discussion I have noticed that most of these examples |start with the statement "I want to design some set of objects to do X and |I want to do this by using langauge feature Y in this way". It do not believe |that there is any meaning in showing that given a contrived set of |circumstances the language can not meet the needs of your program. I agree. C++ could have been done entirely without any overloadable operators. However, I think that would have made it a less desirable language. I am only asking that a "wart" -- an unnecessary restrictive case -- be removed from the language. Let's just say "all operators are overloadable" and get it over with. |To do so |is to expect the language to be all things to all people. On the contrary, people who wish to not allow overloadable operator dot wish to force all people to their point of view that pointers are preferable to references. Such people expect the language to help them restrict what other people can do. I just ask that such a simple and needless restriction be removed. People can decide for themselves whether to use pointer or reference syntax. They don't need a small group of self-appointed experts to decide that for them. |What is important |is whether their is a solution set for your problem, without any contrived |conditions or usages of language features, which maps cleanly to your problem. I disagree. I believe what is important is that the language be clean and orthogonal. Due to its "C" history C++ includes a concept of pointers, whereas other OOPLs have shown that having only references is sufficient. But, due to history, C++ has both pointers and references. Given that the vast majority of operators can already be overloaded, all should be overloadable. Why place a needless non-orthogonal restriction on the language? Why not allow programmers to choose whether to use pointers or to references? Why not allow programmers to choose what operator overloadings are appropriate for their programming? Why allow 40 operators to be overloaded -- but not operator dot ??? |I believe that with some effort a clean approach that does not require |modification of the language is possible for every one of the examples given |so far. That solution starts with rethinking how you want to achieve the end |result and picking an approach that is a good fit with existing language |features. Agreed. The entire concept of pointers in needless in C++ and could be removed. This has already been shown in a half dozen other OOPLs. But such is water under the bridge. C++, due to history, has both pointers and references. I only ask that the choice of which to use be left to the C++ programmer. Why deny this choice? -- C/C++ have historically left the choice to the end programmer to be intelligent enough to decide for themselves how to best do their jobs -- they don't need some "experts" needlessly restricting their choices in a few obscure and non-orthogonal cases. |>But, when we place all the problems |>we've found into one category which we label "smart references" some |>people argue that we're just applying a name to a category we've made up. | |Since "f.thing" and "(&f)->thing are equivilent in a sense smart references |already exist. If you think of "f->thing" as being equivelent to "(*f).thing" |then it becomes clear why "->" is was originaly made overloadable and "." |was not. Since overloading of "*" is allowed how do you overload the implicit |"*" in "f->thing" (i.e. (*f).thing). The method chosen was to allow |overloading of "->". Since "." has not implicit dereference overloading was |not needed. By such an argument operator+ should not exist because its possible to accomplish the same thing through: Matrix A = B - (-C); |>And then when we show specific short examples of the problem then people |>argue that the examples we give are academic and give hack work-arounds. | |I for one do not think using "(&f)->thing" is a hack workaround. It is |quite clear to me what is intended. Tell me which of the following you consider "quite clear" : example A: ["smart references"] Matrix a[100, 200]; Vector v = a[20]; double d = v[40]; example B: ["the 'quite clear' work-around of explicitly converting to smart pointer"] Matrix a[100, 200]; // .... Vector v = (&a)->operator[](20); double d = (&v)->operator[](40); example C: ["smart pointers" used instead of "smart references"] Matrix a[100, 200]; // .... Vector v = (*a)[20]; double d = (*v)[40]; |One reason I have seen given (you must have missed it) is that it alters |the syntax of the language in ways that make it hard to predict the outcome. |Currently "expression.expression" is not allowed, your change would make |it allowable. If this creates side effects then its removal will be far from |easy. I believe you misunderstand me: My proposal is for unary operator dot, just as today there is unary operator->(). Neither allows an expression for the selector. My proposal only requires that which is already required because of opeartor->(). The only change to the language is to allow programmers to choose between writing smart reference classes or smart pointer classes. Expression.expression is not allowed, neither today is expression->expression allowed. The only change is adding the appropriate syntax to allow programmers to program smart reference classes if they so choose, just as today we allow programmers to program smart pointer classes, if they so choose.
steve@taumet.com (Stephen Clamage) (04/04/91)
jimad@microsoft.UUCP (Jim ADCOCK) writes: >I claim one of those guiding principles ought to be that whenever we >have a chance to 1) change the definition to make the language more orthogonal, >removing a special case "wart" WITHOUT negatively impacting existing >code, verses 2) leaving the language the same, arguing the change is not >worth the effort, that we should "almost always" make that effort. Aha! A hidden argument for 'operator dot'. Nice try, but I see through it! >Another second guiding principle ought to be: The ANSI-C++ spec specifies >*language* not *implementation.* There was never any question that the spec must refer to language and not to any specific implementation. However, any language feature, and the resulting totality of the language, must be implementable with current technology with reasonable efficiency; it must not force all users to pay a high price for a feature which they do not use. Thus, we will not see type 'int' required to represent all integers, but only those in an implementation-defined set. >And "my" third guiding principle would be, the ANSI-C++ specification >either calls out *one* behavior for a compiler regards a particular >feature, or leaves *all* interpretation of that feature "implementation >dependent" BUT DOES NOT specify two contradictory *implementations* >either of which [but no other] is acceptible. Consider the right-shift operator in ANSI C. It has one of two specified behaviors: it may, but need not, sign-extend signed integers. It was left with this choice because on some systems it was considered too onerous to require sign extension. By your criterion, >> would be extremely expensive on some systems, or else would be left entirely up to the implementation -- a conforming implementation could just return 0 for any >> operation. Is this what you had in mind? Remember that the standardization effort is cooperative, and many diverse ideas and requirements must be reconciled. The "0, 1, infinity" criterion is often a good guiding principle, but does have its limitations when it collides with the real world. -- Steve Clamage, TauMetric Corp, steve@taumet.com
lord@plasm.esd.sgi.com (the toomlrd) (04/06/91)
This is about the ongoing discussion of an overloadable operator dot. >In order to understand how this would work, I think that you would have >to look at the whole proposal. I'm not sure, but I think that the idea >is to allow something like: > expression.expression >The bare fact of the matter (as I have said many times) is that "." is >plainly not an operator (either unary or binary). It is a selector. If I had to write down the semantics for the dot syntax, I would assume two subexpressions. The type of the right hand expression would be (essentially) `name'. As it stands now, C++ has no run-time representation for names. Consequently, it seems like a big deal to overload dot. If you accept my view -- there is no problem. Its just that all the dot expressions you've ever seen have had lots of constants. The extension I would imagine for . will not really expand the concept, just remove restrictions about what can be done at compile time vs. what can wait till run-time. >In effect, dot acts a bit like the other "scope opener" that we know >about in C++, i.e. the colon-colon. These things are plainly NOT >operators. People who are just learning the language (as well as >experienced users) will just get more and more confused (when trying >to read code) if we start to bend the "normal" rules regarding what may >and may not be overloaded (or treated like an operator). The advantage of the view I suggest (first class names) is that the resulting language has fewer, though more general rules. >I have previously noted that allowing overloading for "." makes about as >much sense as allowing overloading for "{". In both cases the very >idea appears ridiculous, however I actually read a response from one >person who said that (maybe) allowing overloading for "{" would be >a useful and good thing!!! Funny you should say that. Syntacticly, I hope there will never be an operator { -- in fact, it takes a few translations before blocks look like functions at all. On the other hand, blocks are objects with definable types and run time representations. Why not let users define some of the functionality normally implicit in blocks? This leads to many excellent programming techniques usually impossible in C++. >I guess the bottom line is this. What is your opinion regarding how >a language should be designed? Should it be an unbridled, nonsensical >and chaotic mismash of random "bright ideas" which seem like they might >occasionally have some obscure usefulness, or should there be some >rules, some guiding principals, and some *consistancy* in the set of >features provided by a language? There are fewer computer languages than people like to think. A lot of languages that seem similar to C++ really are and if you build clean semantic models of them you see that most bright language ideas capture special cases of an almost universal semantics and give them special names. My conclusion is that what you (the original poster) means by language design is really syntax design. Here the issues are much less `what is the meaning of programs, what programs are possible' much more `which meanings are used most often, and how are those uses best expressed?'. -t
ark@alice.att.com (Andrew Koenig) (04/12/91)
In article <71650@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: > Lets be honest, > some people think C++ shouldn't have had references in the first > place, but are still fighting a read guard to cripple them now that > they're in the C++ language. Without references, the language would need some other way of identifying copy constructors. I can think of no other place where referenes are structurally necessary, though it would be much harder to define input operators conveniently without them. -- --Andrew Koenig ark@europa.att.com
adk@sdl.scs.com (Ajay Kamdar) (04/13/91)
This is a little digression from the regulary scheduled arguments for and against overloading operator-dot. In article <71650@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: >In article <4610@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >|Horse pucky! Prove it! > - Arguments and counter arguments deleted - > >If some C++ programmers consider overloading operator-dot a "bad" idea -- >**** THEN DONT DO IT! **** > That is a supercilious argument. If Ron is right, and if overloading operator-dot is indeed a "bad" idea, advice to not do it just doesn't cut. Most people who have had to support(work with) somebody else's badly written code will testify to that. >Why is it necessary to force your prejudices of what constitutes "good >programming" onto others? Are you really asking that? If you want a simple example of people's prejudices of what constitutes "good programming" and how it affects somebody else's work, read on. Consider the case of function prototypes. I prefer that parameters in function prototypes be named. Some others perfer otherwise. I consider it "bad programming" to not name the function parameters. Some others don't. Now assume that I am the consumer of a class library developed by somebody else, and I just have the object code and some header files. Assume that a .h file has the following prototype for a function: void do_something(int, int); Notice that the function prototype does not have parameter names. If I need to use the function, how do I figure out what arguments it takes? Maybe I can figure out from the context that it takes the arguments something_1 and something_2. But how do I figure out in what order? If I am lucky, the function definiton is in the header file, and I can look at it. But what if it is not? In fact, even if the function definition is available, it is irritating to have to look at the function definition to figure such details out. This is a very simple example of a common problem. The problem becomes really serious when one encounters such situations with complex libraries. Sigh... One can continue ad nauseum with similar examples. Anyway, back to the regularly schedule programming. - Ajay -- Standard disclaimers apply. Ajay Kamdar Mentor Graphics, IC Group Email : ...uunet!sdl!adk