kearns@softrue.UUCP (Steven Kearns) (03/12/91)
I know it is too late now, but here is my opinion on how operator . and operator -> should have been overloadable:' Notice that in the current definition, X->f is really short for (X->) ->f . I find this strange to say the least. Really, we should be able to overload not operator ->, but operator ->f and operator->g(int x) etc... In other words, the real operation being applied to X in X->f is "arrow f". This provides more flexibility than the current system because you are not restricted to eventually returning something for which ->f makes sense. It also seems more intuitive to me. -steve ******************************************************** * Steven Kearns ....uunet!softrue!kearns * * Software Truth softrue!kearns@uunet.uu.net * ********************************************************
jimad@microsoft.UUCP (Jim ADCOCK) (03/16/91)
In article <14.UUL1.3#8618@softrue.UUCP> kearns@softrue.UUCP (Steven Kearns) writes: >Really, we should be able to overload not operator ->, but >operator ->f and operator->g(int x) etc... In other words, the >real operation being applied to X in X->f is "arrow f". > >This provides more flexibility than the current system because you >are not restricted to eventually returning something for which ->f >makes sense. It also seems more intuitive to me. Your suggestion does not provide more flexibility than the current system because the current system allows one do what you are asking for -- albeit not exactly with the syntax you are requesting: ----- extern "C" void printf(const char*, ...); // probably ought to be nested: class Xs_arrow_operators { public: void f() { printf("function X:: ->f()\n"); } void g(int i) { printf("function X:: ->g(int i=%d)\n", i); } }; class X { Xs_arrow_operators arrow; public: Xs_arrow_operators* operator->() { return &arrow; } }; main() { X x; x->f(); x->g(5); return 0; } ---- Thus, by introducing a dummy helper class [which probably ought to be nested] to serve as a target for the current operator->, you can then overload each method in that dummy class as you like. Likewise, if the ANSI-C++ committee chooses to also allow overloaded operator dot, then you'll also be able to meet your needs with operator dot. However, going the other way, if C++ were to require individual overloading of each method to be retargeted, then programmers would have to manually [ or via hack ] implement a forwarding method for each method in order to be able to create a smart pointer or smart reference classes. IE O(N) extra programmer typing -- where N is the number of methods requiring forwarding. This would prevent generally-reusable template versions of smart pointer and smart reference classes -- not to mention make such onerous to program. Whereas, going the other way, having to introduce an intermediate dummy helper class only requires O(1) extra programmer typing. A more interesting question [to my mind] is whether C++ should [have] also allow[ed]: void operator->(class DispatchStyle) // likewise operator dot This would allow overriding of the method of dispatch: void X::operator->(class HashDispatchedMethod method) { hashDispatch(method); } As of today, one can either override the dispatch technique for all members of a class [albeit with grave restrictions] or you can individually override the dispatch for each member individually [via an inline function] but there's no way to break the members of a class into separate categories, where each category uses a different dispatch technique. [please note I am not requesting such functionality -- I'm only mentioning it as a curiousity.]
rfg@NCD.COM (Ron Guilmette) (03/25/91)
In article <14.UUL1.3#8618@softrue.UUCP> kearns@softrue.UUCP (Steven Kearns) writes: > >I know it is too late now, but here is my opinion on how operator . >and operator -> should have been overloadable:' > > >Notice that in the current definition, X->f is really short for >(X->) ->f . I find this strange to say the least. Sorry. It looks like you are fairly confused. Don't feel bad. You are in good company. As any good book about C will tell you, this: ptr->member is really just a convenient "shorthand notation" for this: (*ptr).member Well... at least that *used* to be true. Somewhere along the way, it was decided that this simple relationship was just too clear, too precise, and too easy to understand to allow it to just continue unchanged into C++. So something was added to help muddy the waters. Rather than treating -> as the bit of "syntactic sugar" that it was always meant to be, somebody (and I think I know who) got the idea that it ought to take on a life of its own. So it was reborn. (Or should I say "born again"? :-) And all the faithful now call it an "operator" (which it clearly isn't, any more that my aunt Emma is an "operator"). Of course, it would be one thing if we only *called* -> an "operator", but unfortunately the language (as now defined) further compounds this sillyness by allowing "->" to be overloaded! Of course nobody should bother to suggest at this stage that this may have been a mistake. As Steven says: "It's too late". There is too large of an "installed base" already which depends upon this ill-conceived "feature". That reminds me of a quote that I was reading in some trade-rag recently. Apparently some industry luminary was quoted as saying that Arlington National Cemetery was a good example of a "large installed base". :-) -- // 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.
mvm@caesun6.harris-atd.com (Matt Mahoney) (03/25/91)
In article <4608@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >Of course, it would be one thing if we only *called* -> an "operator", >but unfortunately the language (as now defined) further compounds >this sillyness by allowing "->" to be overloaded! Then again, overloading [] (as in a[i]) is useful (IMHO), but in C that's just syntactic sugar for *(a+i). Allowing -> to be overloaded is just being consistent. ------------------------- Matt Mahoney, mvm@epg.harris.com, 407-727-5431 #include <disclaimer.h> // disclaimer.hpp in Zortech
wmm@world.std.com (William M Miller) (03/25/91)
rfg@NCD.COM (Ron Guilmette) writes: > As any good book about C will tell you, this: > > ptr->member > > is really just a convenient "shorthand notation" for this: > > (*ptr).member > > Rather than treating -> as the bit of "syntactic sugar" that it was > always meant to be, somebody (and I think I know who) got the idea > that it ought to take on a life of its own. > > So it was reborn. (Or should I say "born again"? :-) And all the > faithful now call it an "operator" (which it clearly isn't, any more > that my aunt Emma is an "operator"). > > Of course, it would be one thing if we only *called* -> an "operator", > but unfortunately the language (as now defined) further compounds > this sillyness by allowing "->" to be overloaded! I think the fundamental disagreement is over whether you ought to follow the implicit relationships among overloadable operators or not. In the language as currently defined, there is no relationship among operator+(), operator+=(), and operator++(), even though according to normal semantics you could easily implement both operator+() and operator++() in terms of operator+=(). If you don't supply one of these operators, it's simply undefined, not inferred from the ones you do supply. The reason this relates to "operator->()" is because, in the normal C decomposition "(*ptr).member", it's clear that the "*" _is_ an operator and (as I'm sure you would agree) rightly overloadable. The question is, should "ptr->member" invoke operator*() if "ptr" is an object of a class with operator*() defined? If you think so, then clearly there's no need for a separate operator->(). However, existing C++ practice is that you only invoke an overloaded operator if the operator itself appears explicitly in the text, ignoring the C identities. In this view, you _can't_ invoke operator*() for "ptr->member"; therefore, if you want to be able to overload the conceptual "*" in "ptr->member", you _have_ to allow operator->(). For me, allowing operator->() leads to a more consistent language while still permitting me the syntactic convenience of writing ptr->member instead of (*ptr).member. I agree that the expansion of "ptr->member" to "(ptr.operator->())->member" is a bit strange, but I think the alternatives (implicit invocation of operator*() for "->" or not allowing the ptr->member notation at all) are worse. -- William M. Miller, Glockenspiel, Ltd. wmm@world.std.com
Ari.Huttunen@hut.fi (Ari Juhani Huttunen) (03/26/91)
In article <4608@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: >Of course nobody should bother to suggest at this stage that this may >have been a mistake. As Steven says: "It's too late". There is too >large of an "installed base" already which depends upon this ill-conceived >"feature". It's never too late. And one can't expect a language to change just by _adding_ things. For an analogy, take a look at your Swiss knife. Who ever needs that many blades? -- Ari Huttunen, email: Ari.Huttunen@hut.fi, phone: 90-7285944
gjditchfield@watmsg.uwaterloo.ca (Glen Ditchfield) (03/26/91)
In article <1991Mar25.154013.4044@world.std.com> wmm@world.std.com (William M Miller) writes: >For me, allowing operator->() leads to a more consistent language while >still permitting me the syntactic convenience of writing ptr->member instead >of (*ptr).member. I agree that the expansion of "ptr->member" to >"(ptr.operator->())->member" is a bit strange, but I think the alternatives >(implicit invocation of operator*() for "->" or not allowing the ptr->member >notation at all) are worse. There was another alternative. Don't treat "->" and "." as infix operators; treat "->foo" and ".foo" as postfix operators. That's how the ANSI C standard defines them. struct C { int operator ->foo(); }; This wouldn't have helped programmers who want to define smart pointers.