Path: utzoo!attcan!uunet!microsoft!jimad From: jimad@microsoft.UUCP (Jim ADCOCK) Newsgroups: comp.lang.c++ Subject: Re: Assignments to reference variables [ and operator.() ] Message-ID: <57684@microsoft.UUCP> Date: 24 Sep 90 19:15:20 GMT References: <8445@jarthur.Claremont.EDU> <57570@microsoft.UUCP> <1677@lupine.NCD.COM> Reply-To: jimad@microsoft.UUCP (Jim ADCOCK) Organization: Microsoft Corp., Redmond WA Lines: 179 In article <1677@lupine.NCD.COM> rfg@NCD.COM (Ron Guilmette) writes: |In article <57570@microsoft.UUCP> jimad@microsoft.UUCP (Jim ADCOCK) writes: |> |>-- Please join me in lobbying the ANSI C++ committee to correct this oversight |>in the language definition. Overloading operator.() makes equal sense for |>reference classes as overloading operator->() for pointer classes... | |Finally, Jim and I have found something to agree on. :-) | |I'd say that Jim is correct is saying that treating either `.' or `->' as |if they were OPERATORS (kinda like other operators) makes equal sense, |i.e. *NONE*! Allowing overloading for either of these makes about as |much sense as allowing overloading for `{' or `}'. I kind of agree, but I am not one for suggesting that "features" be removed from the C++ language. I am therefor one who suggests trying to make "features" of the language as self consistent as possible. Lacking overloaded op. forces a gratuitous lack of symmetry between usages of pointers and references. I think the best solution to the pointer verses reference syntax dilemma in C++ is just to give the user of the language the choice to use either in a given situation. If we had history to do over, it might have been better if compilers were allowed to apply . directly to pointers, implicitly dereferencing the pointer first, rather than introducing a separate -> syntax for pointers. However, that's water long gone under the bridge, and we need to try to make the best out of the situation today. If we can fully enable the use of references in everyday programming, then perhaps we can de-emphasize some of the alias problems with pointers that have never been resolved, and are re-rearing their ugly heads in C++. |Look folks, just because a particular C++ token contains some non- |alphanumeric characters does not make it an operator! Right. For that to happen the author[s] of the language has to say: "This particular token is an operator." Said comment has been made for "->", has not been made for "." I jump the gun in referring to "op.", because I am persuing an analogy to op-> -- an analogy that Ron seems to buy into. Does Ron seriously suggest that overloaded op-> be removed from the language? |OK. Back to basics. What is `->'? | |Well, it is (syntactic sugar) shorthand notation for `*.' (i.e. |dereference and select). So whenever I write: | | a->b | |(in C anyway) that's always equivalent to: | | (*a).b | |The meaning is clear and unambiguous. Apply the prefix unary dereference |operator to the thing on the left, and then select out a member from the |result. Likewise foo[n] is [was] "syntactic sugar" for *(foo+n). When operator overloading was first allowed in C++, the choice was made that the decision to keep or not keep the historical equivalences from C in the overloaded operators was up to the class programmer's discretion. Given that the appropriate "operator" overloadings are permitted, a class programmer can choose to copy these historical equivalences from C -- implicitly assuming that the C++ class user comes from a C background, and thus has these equivalences ingrained on their consciousness -- Or a class programmer can choose to ignore these historical meanings, possibly confusing and pissing off the "C" audience for those classes. But is it good to prohibit the operator overloadings necessary to enable a class programmer from making these "C" analogies, for fear that a class programmer might abuse these new found freedoms? |I do object (most violently) however to any attempts to call the selector |`.' a `binary operator' (or to treat it as though it were one). Obviously, |it isn't. Why not rather, allow me to call it what I like [perhaps you'd be happier if I call it a "rose?"] and argue for or against the feature based on its impact on C++ programmers, as opposed to its impact on C++ language lawyers? |For all of the binary operators that *I* know of, either the left or the |right operands may be arbitrarily complex *expressions* (so long as these |expressions evaluate to some type of value which is appropriate for the |given category of operator). When I was arguing for "op." by analogy to "op->", I was hoping that people would realize that both would be unary operators [as op-> is now] op-> is a member function of the type of its lhs, returning an object or primitive of type known at compile time, that the compiler can then reapply either an overloaded op-> to, or failing to find such, then perform the traditional compile-time binding to the rhs. |This is clearly *not* true in the case of the selector `.'. For the |selector, the thing on the right *must* be a (qualified or unqualified) |identifier which designates a some member belonging to the type of the |thing on the left. The thing on the right *cannot* be an arbitrarily |complex expression. It must be an identifier. Furthermore, the identifier |*cannot* refer to any complete *object*. Rather, it must refer to a |*member*. No more true nor less true than op-> |So the selector is *not* an operator. Period. Allowing overloading for |it would make about as much sense as allowing overloading for `{' or `}' |or `::' or `"'. "." is not an operator until it can be overloaded. It is then an operator. Like op->, it can make sense to turn "." into a unary operator, because it certainly has an object on the lhs to bind to. Other combinations of tokens with an object on one side, or the other, or both sides, could also be candidates for similar promotion to "operator" status, but I leave it to someone more flame resistant than myself to make such proposals, if they feel so motivated. In particular, it might be interesting to allow an extension to the language of: object1 -> object2 and object1 . object2 [IE allow binary overloading of op-> and op. where both the lhs, and the rhs are unambiguously objects, not field selectors] This would allow programmers a reasonable option for implementing message dispatch algorithms [such as hashed dispatch] other than that built into the C++ compiler, while hiding the exact mechanisms of such dispatch from the class user. [Alternately, the class programmer with a need for non- standard dispatch mechanisms must expose the class user to those dispatch mechanisms via non-standard method invocation syntax. Thus we're back to the standard dilemma: The overloading proponent says that this or that overloading is necessary so that I can appropriately encapsulate details of my class implementation. The overloading opponent says that each new overloaded feature of the language is yet another opportunity for hacks to write code that confuses and confounds] --But, this would entail larger changes to the language, and *I* am not making such a proposal. I am suggesting that allowing unary op. like unary op-> would fix a lot of the current syntax problems for users exposed to confusing mixtures of pointers and references with no apparent rhyme nor reason. |Likewise, since `->' is just a shorthand notation for a combination of |an operator (i.e. unary prefix dereference) and the selector, allowing |overloading for `->' make as little sense as allowing it for the selector |all by itself, i.e. none whatsoever. | |I can't understand why Bjarne and Jim and others have so much difficulty |seeing the fundamental irrationality of allowing operator overloading |to be done to things which are clearly not operators. Probably because if one looks at the problem from a different angle, the fundamental irrationality goes away. |If they really think that this is such a swell idea, then I challenge them |to tell me (and everyone) why they are not suggesting allowing `operator{' |to be overloaded. 1) Unlike op. , no one has presented a reasonable proposal why it might be good to allow doing so. 2) Unlike op. , one cannot argue that either the lhs or the rhs of "operator{" is an object such that the appropriate overloaded "operator{" can be selected. |If there are any rules for what should be called an operator and what should |not, and what should be overloadable and what should not, I'd like to see |them! If these rules are at all consistant, if they make any sense |whatsoever, and if they still would seem to permit -> to be overloaded, |I'll eat my hat. My proposal for such a set of rules is simply: 1) One or both sides of the proposed "operator" needs to be certainly an object, so that a member function can be unambiguously selected based on the type[s] of those object[s]. 2) Someone needs to make a strong argument for how allowing such to be an overloaded operator is going to solve real-world programming problems. 3) It better not cause wide-spread changes throughout the language.