home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.std.c++
- Path: sparky!uunet!microsoft!hexnut!jimad
- From: jimad@microsoft.com (Jim Adcock)
- Subject: Re: Alternatives to operator.()
- Message-ID: <1992Jul27.204820.8400@microsoft.com>
- Date: 27 Jul 92 20:48:20 GMT
- Organization: Microsoft Corporation
- References: <Brqq7D.97w@world.std.com> <1992Jul23.024159.18039@microsoft.com> <BruME9.HGJ@world.std.com>
- Lines: 202
-
- In article <BruME9.HGJ@world.std.com> wmm@world.std.com (William M Miller) writes:
- |I wonder if it ever occurred to you that the explanation for my
- |continuing to maintain my objections is that we disagree about the
- |validity of your arguments, rather than that I have forgotten them or
- |didn't understand them in the first place?
-
- I considered such a possibility but I had to reject this hypothesis in
- the face of your continued misstatements about my proposal. If you
- understood my proposal, you would not make misstatements about it, but
- rather would argue against it using true statements.
-
- |expr addressing context scope
- |---- ------------------ -----
- |i stack frame of f() f()
- |
- |::i program static file
- | storage
- |
- |x.i x class X
- |
- |(*xp).i object to which xp class X
- | points (indirection)
- |
- |xp->i object to which xp class X
- | points (indirection)
- |
- |xr.i object to which xr class X
- | refers (may not be
- | an indirection,
- | depending on
- | implementation)
- |
- |In each case, you look up the name "i" in the implied scope, take the
- |corresponding offset out of the symbol table, and add it to the base
- |address implied by the addressing context.
-
- Your statement is incorrect in both the (*xp) and xp-> cases above,
- therefore how can it be an argument against operator.() ?
-
- I keep making this point, and you keep ignoring it:
-
- The language ALREADY permits operators *, &, and -> to be overloaded, yet
- you keep making arguments pretending that these overloadable operators
- don't ALREADY exist. You insist that operator.() must be a simple
- binding. Yet this statement is already false within the language.
- If your statement were true, then the following two expressions would
- have to be identical:
-
- (*pfoo).doSomething();
-
- pfoo -> doSomething();
-
- yet the language ALREADY permits such a statement NOT to be true.
- Dot therefore, already DOES NOT represent "just" a simple binding,
- because overloadable operators &, *, and -> ALREADY "break" this
- statement. ON THE CONTRARY, then, we need overloadable operator.()
- to ALLOW such relationships to continue to be made, in the face of
- ALREADY overloadable operators &, * and ->
-
- |Whether you use the
- |resulting address in an lvalue or rvalue context is immaterial to the
- |process. The role of "." is simply to indicate that the expression
- |preceding the "." is to be used to determine the addressing context
- |and scope for the interpretation of the name following. This is
- |exactly analogous to what "::" and the absence of qualification do.
-
- Again, the fact that -> and * can be overloaded INDEPENDENTLY
- ALREADY contradicts your statement, since they already allow
- the historical relationship:
-
- (*pfoo). <==> pfoo->
-
- to be violated. On the contrary then, "." must represent the DIFFERENCE
- in the operation of (*pfoo) and pfoo-> so that the overall relationship
- can be maintained.
-
- | x.i;
- |
- |This isn't detailed enough. Using your terminology, it should read,
- |"reference to the object named 'i' within the object 'x'", which is
-
- Wrong. If this were my terminology, then in the following:
-
- px -> i;
-
- would mean "i within the object referred to by px"
-
- which is clearly a false statement given that the language ALREADY
- allows operator-> to be overloaded.
-
- |Just out of curiosity, did you ever program in Bliss? If I recall
- |correctly, it has this idea that every name is really just a pointer.
-
- No, on the contrary, I program in C++, which has this idea that every
- name is really just a reference.
-
- |If the target class has a member operator and you want to use it via
- |the smart reference, you MUST provide a forwarding function under your
- |proposal. Neither your operator.() nor the conversion function
- |alleviates this necessity.
-
- I have pointed out that there is a tiny fixed set of unary member operators
- where ARM requires the LHS to be a member. ARM pages 333-337 lists these
- as I have previously noted. The pertinent member functions are as follows,
- as I have previously noted:
-
- 1) Assignment: operator=()
- 2) Function Call: operator()()
- 3) Substcripting: operator[]()
- 4) Class Member Access: operator->()
-
- That's It. Since there is such a small fixed set of possible functions,
- this does not represent a "real" argument against operator.(), but rather
- represents an argument in choice of implementation syntax. This small
- FIXED set of operators could be implemented using templates, or macros,
- for example. This is a very DIFFERENT situation from forwarding member
- functions in general, where the names of the member functions cannot be
- predicted in advance, and where the set of functions to be forwarded IS NOT
- tiny.
-
- Further, as I have previously noted, these set of four functions are exactly
- the ones that an implementor of a reference class MIGHT NOT want to have
- forwarded! Thus, NOT having these things forwarded automatically might
- argubly be considered a "feature." IF the smart reference class implementor
- CHOOSES to have one or more of these tiny fixed set of member operators
- forwarded, that CHOICE is TRIVIAL to implement.
-
- BUT, what if the class implementor CHOOSES NOT to forward one of these
- operators? What if a "smart reference" implementor CHOOSES that operator=()
- should mean -- BY DEFAULT -- assign one smart reference to another
- [such as references are implemented in just about all other OOPLS]
-
- ref1 = ref2; // assign ref2 to ref1 NOT assign refed-ob2 to refed-ob1
-
- Your position would prohibit such a CHOICE.
-
- |If you "CHOOSE" not to provide such
- |forwarding functions, the desired operations simply won't be available
- |via the smart reference. I agree that you have reduced the burden of
- |writing forwarding functions in your proposal, but you have not
- |eliminated it.
-
- Wherever there is a CHOICE, there is a burden. Some committee members
- would keep *all* such choices from the programmer -- but only for
- operator.() out of all the operators. Again, if operators *, & and ->
- were not ALREADY in the language, I could see this. BUT operators *,
- & and -> ARE ALREADY in the language. These committee members special
- case arguments against ONLY overloading operator.() out of this set
- of operators is silly. The argument has already been decided. Overloaded
- * & -> ARE in the langauge ALREADY, therefor so should overloadable operator.()
-
- |No circumlocution is needed in the smart reference's member functions,
- |agreed, but that was not the context I was describing. If there is a
- |"metaoperation" to be performed on the smart reference itself, the
- |circumlocation *is* necessary. Such metaoperations might include
- |status queries, cache invalidation, network rerouting, etc.
-
- Again, this represents an implementor CHOICE. No one forces the programmer
- to make these choices, and no one forces the programmer to use operator.()
- CHOICES available to the implementor REMAIN te CHOICE to forward each
-
- function independently, doing with each as they choose, inventing some
- new syntax to represent NOT forwarded, etc:
-
- ref.notForwarded();
- ref->notForwarded()
- local(ref).notForwarded();
- notForwarded(ref);
-
- etc, etc.
-
- These all represent implementor CHOICES. If the language is to offer
- any convenience to the programmer, someone somewhere has to decide that
- that convenience IS. If that convenience fails to meet the needs of some
- programmer in some situation, then the programmer needs to be able to
- sidestep the "convenience." You argue that because a language default
- doesn't meet the needs of everybody always, we shouldn't offer it to anybody
- ever. This is a vacuous argument.
-
- |I have explored your proposal. The three disadvantages are still
- |there. Refusing to acknowledge them doesn't make them go away. There
- |is room for discussion about the degree to which they are significant,
- |but denial doesn't move that discussion forward very much.
-
- I am happy to acknowledge strengths and weaknesses in my proposal.
- However, I will continue to try to refute erroneous statements that you
- or any other people make against it. Again, rather then keep making
- vacuous arguments that "my" proposal is "half-empty" why don't *you*
- write down *your* counterproposal for how something, anything else would
- work that is better. Because right now, your counter-proposal is not
- "half-empty" -- rather it is totally empty, because you have refused to
- counter-suggest any CONCRETE counterproposal, such that you, I or the
- other guy can COMPARE two CONCRETE proposals, in order to discover
- which might be better. Again, put up or shut up. Either come up with
- something better, or get out of the way.
-
- I suggest that if you or some other committee member puts in the work to
- TRY to come up with a better counterproposal, you will quickly find out
- that my proposal isn't nearly as bad as you would suggest. But you refuse
- to address that possibility, by refusing to do any such CONCRETE work.
-
-
-