Topic: Handling of operator . proposal
Author: mat@mole-end
Date: Tue, 21 Jul 1992 09:55:06 GMT Raw View
In article <1992Jul21.005444.836@microsoft.com>, jimad@microsoft.com (Jim Adcock) writes:
> In article <1992Jul18.211602.11671@mole-end> mat@mole-end writes:
> |Attending this last meeting was an eye-opener for me. (Although those
> |eyes spent quite a bit of time glazed over by the material.) The next
> |meetings will be held in Boston (November) and Portland (March). I
> |strongly suggest you attend.
> I strongly suggest you [and others] suggest HOW I might attend?
> Am I to click my heels together three times while reciting:
>
> "There's no place like an ANSI C++ meeting!"
I'm afraid it's much simpler than that. It involves a rare, hard-to-get
thing called _money_. I think you can sign up as an x3j16 Observer for
a half-year now that the year is half-gone. I can't tell you what airfare
to Boston will be in the fall, but I'm pretty sure it will involve money,
too :-). Oh, and a week of your time, which might have to come out of
your vacation. (I know of at least several people who brought their families
along to Toronto; I'm sure they found something to do. Boston should be
able to keep people busy for a week as well. Portland, I'm not so sure
about.)
--
(This man's opinions are his own.)
From mole-end Mark Terribile
uunet!mole-end!mat, Somewhere in Matawan, NJ
Author: mat@mole-end
Date: Sat, 18 Jul 1992 21:16:02 GMT Raw View
In article <1992Jul13.170842.5433@microsoft.com>, jimad@microsoft.com (Jim Adcock) writes:
> I'd be happy to meet or beat the quality of "analysis" that was done
> to justify these decisions. [I already have] I just don't see why I have
> to "prove" my position but none of these other decisions needed any
> justification.
>
> Why is one standard of "proof" required for me and a different standard
> of proof required for some committee member's ideas?
Ouch! Jim, one of the committee members is championing a proposal
(which might or might not have been her own) on which she has written
three position papers, and for which other members have written several
analysis papers. They really _do_ put in the time, which is the reason
that nothing seems to get done! And why, given that they haven't got
time in one meeting to look at their entire list, they prefer to look at
those proposals for which there remains the least work to be done.
Attending this last meeting was an eye-opener for me. (Although those
eyes spent quite a bit of time glazed over by the material.) The next
meetings will be held in Boston (November) and Portland (March). I
strongly suggest you attend.
> People who want to write test programs to see how operator.() would work
> in practice need only use operator->() instead. You will find writing
> programs this way will be confusing as hell, but other than "just syntax"
> your programs will work identical to if operator.() was in the language.
>
> But, this is the whole point to introducing operator.() into the language --
> namely people ALREADY ARE using operator->() in inappropriate situations
> BECAUSE they cannot use operator.() and their programs already ARE working --
> its just that they are confusing as hell!
Can you show us some examples? If you can boil it down to a few pages
of half-page examples, you might make a strong case for the proposal.
--
(This man's opinions are his own.)
From mole-end Mark Terribile
uunet!mole-end!mat, Somewhere in Matawan, NJ
Author: jimad@microsoft.com (Jim Adcock)
Date: 21 Jul 92 00:48:28 GMT Raw View
In article <1992Jul18.211602.11671@mole-end> mat@mole-end writes:
|> People who want to write test programs to see how operator.() would work
|> in practice need only use operator->() instead. You will find writing
|> programs this way will be confusing as hell, but other than "just syntax"
|> your programs will work identical to if operator.() was in the language.
|>
|> But, this is the whole point to introducing operator.() into the language --
|> namely people ALREADY ARE using operator->() in inappropriate situations
|> BECAUSE they cannot use operator.() and their programs already ARE working --
|> its just that they are confusing as hell!
|
|Can you show us some examples? If you can boil it down to a few pages
|of half-page examples, you might make a strong case for the proposal.
Man, I have been TRYING to get people to look at some examples, but I
just cannot seem to get them to READ such. As I noted in my "rebuttal"
paper, these issues are well-noted by Coplien, among other people. To
see examples, just take your copy of Coplien, open to the index page,
look up "operator->" and then flip to the pages listed there. You won't
find any examples of operator.(), because operator.() isn't permitted.
You WILL find examples of Coplien bemoaning the lack of operator.() and
then explaining how he has to try to make do with operator->() instead,
even though the syntax is incorrect. Reading HIS half-page examples
using operator->() you will notice that nine times out of ten HIS examples
are using operator->() on classes that need to follow the "value semantics"
of operator.() NOT "pointer semantics" meaning that operator->() is an
inappropriate syntax for the situation.
See for example Coplien page 162:
"This approach puts the burdon on the user of the class to remember whether a
member function is forwarded or not, and to use the appropriate syntax. If
this is a troublesome inconvenience, then operator-> should not be used and
each member function should be treated individually as in the 'TEDIOUS'
example above."
[emphasis mine]
Author: jimad@microsoft.com (Jim Adcock)
Date: 21 Jul 92 00:54:44 GMT Raw View
In article <1992Jul18.211602.11671@mole-end> mat@mole-end writes:
|Attending this last meeting was an eye-opener for me. (Although those
|eyes spent quite a bit of time glazed over by the material.) The next
|meetings will be held in Boston (November) and Portland (March). I
|strongly suggest you attend.
I strongly suggest you [and others] suggest HOW I might attend?
Am I to click my heels together three times while reciting:
"There's no place like an ANSI C++ meeting!"
"There's no place like an ANSI C++ meeting!"
"There's no place like an ANSI C++ meeting!"
Author: jimad@microsoft.com (Jim Adcock)
Date: 10 Jul 92 20:00:58 GMT Raw View
In article <1992Jul10.005434.24354@fcom.cc.utah.edu> swillden@news.ccutah.edu (Shawn Willden) writes:
| Overloading operator. breaks a fundamental identity we inherit
| from C, namely that for a pointer p to a struct, p->foo is
| equivalent to (*p).foo.
|
|True. And if I'm not mistaken, operator. would be the first to break
|a fundamental identity on a builtin type (a pointer).
Not true. A "fundamental identity" was already previously broken
by previous operator overloading. Note the following example:
Foo foo;
Foo* pfoo = &foo;
Foo& rfoo = *pfoo;
if (&foo != &rfoo)
{
cout << "what happened to THIS 'fundamental identity'?\n";
}
-- which is *already* broken. Again, this is back to the original first
point that started this whole argument about two years ago now. Namely
that the stated reason why operator.() cannot be overloaded is that it
has built-in meaning. BUT unary operator&() CAN be overloaded yet it TOO
also has built-in meaning. Therefore, logically, if anyone cared about
a logical language design, the reason for not allowing operator.() cannot
stand.
|>Philosophically, . is not an operator. Therefore it should not
|>be overloadable.
Philosophically one could argue that . is not an operator until such
time as overloadable operator->() was added to the language. As such
point in time the argument that . is not an operator does not make sense.
If . is not an operator then it follows that x-> should continue to
have its built-in meaning of (*x). in which case overloading unary
operator* should "automatically" change the meaning of "x->" to be
the same as the standard definition (*x). -- since the . part of this
equality "is not" an operator then there should be nothing in "->" that
isn't already in *x and therefor "->" should not be overloadable independent
of unary *
BUT
"->" CAN be overloaded independent of unary * which in
turn means that any difference in overloading * verses -> has to be
attributable to the . part of the equality in "x->" <==> "(*x)."
so, philosophically speaking, operator->() ALREADY represents an overloading
of . -- namely any difference between "->" and "*" can only be attributed
as an overloading of the implicit . in the traditional "x-> <==> (*x)."
equality. Adding an EXPLICIT ability of overload . to the ALREADY IMPLICIT
ability to overload the implicit . implied by "->" merely ALLOWS programmers
the ability to MAINTAIN the historical analogy. Why is it that the people
who claim to support these historical analogies are the one's preventing
programmers the ability to maintain these historical analogies ????
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Sat, 11 Jul 1992 01:01:28 GMT Raw View
In article <1992Jul10.005434.24354@fcom.cc.utah.edu> swillden@news.ccutah.edu (Shawn Willden) writes:
>I've been following this debate/flame-war for some time and with
>considerable interest (and some amusement :-) ) and I've decided to
>jump in, so, here's my $0.02 worth:
>
>I agree with Jim's argument that for the sake of symmetry we should
>probably include operator. in the C++ language. The arguments I've
>heard *against* operator. (and my responses are):
Just invoking 'symmetry' is not enough. It is inspiration
for analysis---you still have to do the analysis.
I want to see how it is used. How do you write a smart
ref class using ., ->, & and *. What identities *ought* to be
preserved and why? How does overloading operator. actually
*help* in preserving these identities?
How can I replace class X in my program with a smart
mechanism? Suppose for example X uses the "orthodox" design
for a first class object. Now I require that reference counting
be used. I want to systematically change my program to use
the new mechanism. What are the rules for doing this,
show me the class design.
Now compare this with the case *without* operator.
>
> operator-> and operator. are not a good way to build
> SmartPointers and SmartReferences. A better way should
> be developed and both constructs should be removed.
>
>I agree, but until a better way is proposed I don't think this matters and
>it's essentially irrelevant to the "symmetry" argument in any case. Of
>course, we've also heard the argument (which crops up now and again) that
>overloadable operators are a Bad Thing in general, in which case I must
>say "Find another language."
Bjarne proposed I believe a forwarding mechanism:
class X : *p { Y* p; ... }
where x->mem resolves to p->mem, but it proved hard to use.
>
> operator. would require all kinds of hard-to-implement and
> confusing name-space searches.
>
>Nonsense, operator. is a UNARY operator.
>
>Though a general-purpose forwarding operator would be better, I haven't
>yet seen a proposal for one. It may be worthwhile to discuss the
>possibility, but that's not what we're currently considering.
See above. It looks good, I can't see why it wouldn't work
nicely. But the fact is that experiment showed otherwise.
>
> If I overload operator. I can't access the members of my class
> without some awful-looking workaround like (&foo)->bar().
>
>If you want to access your class members then DON'T overload operator.!
>("Doctor, when I do that it hurts!" "Then don't DO that!!") As Jim
>pointed out, overloading operator. would not affect the ability of member
>functions (like operator.() operator&(), etc.) to call OTHER member
>functions.
Besides, you CAN if you also overload operator-> to do this.
class X { operator.(){}
X* operator->(){return this;}
mem();
};
X x;
x->mem();
Would you ever want to overload BOTH -> and . in the same class
to do 'smartness'??
>
> Overloading operator. breaks a fundamental identity we inherit
> from C, namely that for a pointer p to a struct, p->foo is
> equivalent to (*p).foo.
>
>True. And if I'm not mistaken, operator. would be the first to break
>a fundamental identity on a builtin type (a pointer). All of the other
>identities (e.g. a++ == a+=1 == a=a+1) still hold for builtin types
>though they may break for user-defined types. This is true and seems
>to be a problem.
Actually, making operator. overloadable would seem to
provide scope for PRESERVING some identities that would otherwise
be broken --- far from being against the proposal, this argument
is perhaps the best argument FOR the proposal. It IS the symmetry
argument!
>Some questions:
>
> 1) Why do we consider a pointer a builtin type? Would
> it make more sense in C++'s more type-safe world to
> say that an int* IS A TYPE in and of itself and that
> the declaration of a new type actually creates two
> new types, an object type and a pointer type? Thus
> declaration of class foo creates type foo* as well
> as type foo - meaning the identity no longer applies
> because foo* is a user-defined type.
This is getting into a new area. It is a great idea.
When class X is declared the compiler generates class X* automatically,
but you can override the definition:
class X* { .... }
Even more poweful is
class X * X { ... }
which leads to
class X * Y { ... }
i.e. we are heading to multi-methods!
You will note that the built-in meaning of pointer is what makes
the diagram below commute:
X =========> X*
| |
V V
Y ==========> Y*
where Y is derived from X and X* is auto generated meaning for class X*
and class Y*. To say it commutes is to say you get Y* the same
by following either path.
It is precisely this property that enables the pointer based
polymorphism with single dispatch to work. In other word,
class Y* is derived from class X*, and also, class Y* is generated
from class Y and the results of these operations are the same.
[A similar diagram can be drawn for class X&]
> 2) Assuming we maintain the position that a pointer is a
> pointer is a pointer, type notwithstanding, how important
> is this identity? What confusions could arise from
> breaking it?
>
The identities are crucial.
>This seems to me to be the most serious objection I've seen.
NONONONO it is the strongest argument IN FAVOUR.
Wait, I overreact: it is *potentially* the strongest argument
in favour. I need to be shown *how*. Jim has already done this
to some extent. A tight theoretical analysis would really help
the case.
>
> Philosophically, . is not an operator. Therefore it should not
> be overloadable.
>
>Okay... this one doesn't bother me one bit. Should it?
Yes. It means operator. is open to abuse. There will
be more potential for abuse and confusion. But that will be
outweighed (perhaps?) by the advantages of IMPROVED readability,
that is, the ability to have tryly transparent smart
mechanisms. Jims argument seems to me to be that without
operator . that transparency cannot be achieved.
>
> If operator. can be overloaded I will have to look to see
> if it has been every time I see something of the form foo.bar.
> True.
Also false. The whole idea of smart classes is that
you *dont* need to look! You just use it. You have to assume
the author of the smart mechanism did it right.
If I define a string class, you just use it, you dont need
to look to see if I manage the memory properly. I just
say "Use strings as you would an 'int'". You don't even need
to know they are a class. You need a manual on how to use them,
only the compiler needs to see the header file.
How do I *write* a string class reliably? Well,
I read Coplien's book and use the "orthodox" idiom and
it just works.
How do I *write* a smart mechanism for class X?
I WANT TO SEE THE ANSWER TO THAT!!
>
>True. This would be a very serious objection IMHO, if it weren't already
>a problem. It would seem to make sense to allow only operators which don't
>have a predefined meaning for classes to be overloaded, which would exclude
>operator. and operator& as well. operator-> by default means nothing when
>applied to a class, so we know that it must be overloaded when we encounter
>foo.bar (and know that foo is a class object), likewise when we see foo++,
>foo--, foo+=fred, *foo, etc. So this argument indicates that it would
>probably be a good idea to remove operator& if we're going to disallow
>operator. A counter-argument that some may consider valid is "But foo.bar
>is much more common than &foo so it would be more problematic." I can't
>say anything about the validity of this claim.
If you don't USE operator., nothing extra is broken.
If you abuse it, like any other operator or mechanism in C++,
everything is broken.
So the question is: how do you use it properly,
and, show that this use is superior to what can be
done *without* operator. Appeals to symmetry are attractive
but inadequate. *Proof* would be best but is perhaps asking
too much. That leaves *convincing demonstration*.
For convincing demonstration we need a compiler that
has been extended. Perhaps someone might extend GNU?
>
>In sum:
> It may be a good idea to disallow overloading of operator-> and
> operator&.
Out of the question for -> for historic reasons.
>If we don't want to do that, it would seem to make
> sense to allow overloading of operator.
*seem* is grossly inadequate. you agree? we need more
than *seem*.
>UNLESS the identity
> p->foo == (*p).foo turns out to be an important one AND we assume
> that any pointer is a builtin type (that is, that foo* is not
> implicitly declared when foo is defined).
>
>Did I miss any of the objections to operator.? Anyone disagree with my
>stands on the objections I mentioned?
Objection:
It will complicate the language.
Refutation.
No, it will simplify it.
Objection:
It will break identities.
Refutation:
Yes, but it will allow others to be preserved
that cannot be preserved any other way.
Objection:
It will be hard to implement.
Refutation:
No, it is trivial. [Evidence: someone please
try this out on GNU]
Objection:
No one knows how to use it properly.
Refutation:
Not suprising, we need to have it to use it.
Objection:
There is no prior art.
Refutation:
This is true. We need to make some prior art.
>
>Shawn Willden
>swillden@cc.weber.edu
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: jimad@microsoft.com (Jim Adcock)
Date: 13 Jul 92 17:08:42 GMT Raw View
In article <1992Jul11.010128.12539@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
| Just invoking 'symmetry' is not enough. It is inspiration
|for analysis---you still have to do the analysis.
Please show me such an analysis.
Show me the analysis that was done to justify introducing postfix ++ given
that prefix ++ was in the language?
Show me the analysis that was done to justify introducing operator->() in
the language?
Show me the analysis that was done to justify changing the language in
the base document to support Humpty-Dumpty const?
Show me the analysis that was done to justify the restriction against
operator.() in the first place?
I'd be happy to meet or beat the quality of "analysis" that was done
to justify these decisions. [I already have] I just don't see why I have
to "prove" my position but none of these other decisions needed any
justification.
Why is one standard of "proof" required for me and a different standard
of proof required for some committee member's ideas?
|Would you ever want to overload BOTH -> and . in the same class
|to do 'smartness'??
I think that if one were silly enough to want to implement a smart pointer
to a smart ref you might run into this situation. But, note that one can't
take a pointer to a ref in the built-in case.
| Objection:
|
| There is no prior art.
|
| Refutation:
|
| This is true. We need to make some prior art.
The prior art is operator->(). Its like the language only had operator-()
and someone suggested that operator+() should be added. Or that only
prefix++() was supported and someone suggested that postfix ++ be added.
People who want to write test programs to see how operator.() would work
in practice need only use operator->() instead. You will find writing
programs this way will be confusing as hell, but other than "just syntax"
your programs will work identical to if operator.() was in the language.
But, this is the whole point to introducing operator.() into the language --
namely people ALREADY ARE using operator->() in inappropriate situations
BECAUSE they cannot use operator.() and their programs already ARE working --
its just that they are confusing as hell!
Author: jimad@microsoft.com (Jim Adcock)
Date: 06 Jul 92 19:50:15 GMT Raw View
In article <1992Jul2.212547.897@murdoch.acc.Virginia.EDU> gs4t@Virginia.EDU (Gnanasekaran Swaminathan) writes:
| a.something(); If operator.() is allowed, I have to look into the
| class A to find out whether it is A::something()
| or A::operator.(). ... something(), thereby
| hindering the readability of the program heavily.
This situation already exists today, in the case of smart pointers:
a->something();
could mean A::something() or it could mean A::operator->() ... something()
Thus your argument COULD be reason enough to REMOVE operator->() from
the language, but it is NOT a reason not to allow BOTH operator.() and
operator->().
There is no good argument for ALLOWING this "problem" in the one case,
but not in the other case. That would be illogical.
Author: jimad@microsoft.com (Jim Adcock)
Date: 07 Jul 92 01:27:49 GMT Raw View
In article <BqvL07.BsF@world.std.com> wmm@world.std.com (William M Miller) writes:
|2) I'm as unconvinced as ever, perhaps more so, that operator.() is the
|right way to go about adding smart references to the language.
Then write up a "better" proposal that "fixes" your current complaints
with my proposal. Then both you I and any others can debate the relative
merits of your proposal verses my proposal. My "gut feeling" is that WHEN
you attempt to write up such a "better"
proposal you will find out it doesn't "work." I know that I tried to
come up with several other approaches before settling on the current approach,
because I couldn't get these other ideas to "work."
What doesn't do anyone any good is vacuous "gut feelings" that "something"
might be better. I can't respond to such "feeling" -- my gut feeling today
is that I've had too much coffee without lunch....okay, but who can respond
to my "gut feelings" ????
Write up something concrete and I will be happy to respond to your ideas
and to support them if I think they are better than mine.
|I have the following objections to your proposal (not in priority order):
|
|First, I do not believe that "." is an operator in the same sense as the
|currently overloadable operators; I'll say more about this in a followup to
|the article in which you specifically asked about this issue.
I will thus respond there also.
|Second, a circumlocution is required to access members of the smart
|reference object. In your paper, as I recall, you suggest
|
| ( &smart_ref ) -> member
|
|as the workaround. Another
Not as "the" workaround but rather "a" workaround. Note that most of the
time in using a SmartRef class the time that you need to refer to members
is only in the internal implementation of the SmartRef class, and in doing
so since operator dot is a unary operator, the only object you need to
refer to is the "this" object, thus *in practice* the workaround is simply
to write the following inside a given member function of SmartRef:
member
IE "this" is implied, neither a "." nor a "->" nor any other operator need
be specified, so "in practice" when writing a smart reference class this
problem *simply does not arise*.
Thus "in practice" the workaround to this "problem" is simply that the
"problem" does not arise at all.
|possibility was suggested in the
|Koenig/Stroustrup paper, namely putting all the members requiring access
|into a base class and just having the operator.() in the derived class; this
|style would allow access to the members by casting the smart reference
|object to a reference to the base class.
Fine, this is an implementors choice of preferred style.
|I think the necessity of these circumlocutions detracts from your proposal.
It only detracts from my proposal if you come up with a "better" proposal
that doesn't have these problems, and which also solves the "gap" and
"contradiction" problems previously mentioned about page 330 in the ARM.
|We have a perfectly good set of scope rules that handle similar sorts of
|things in inheritance; it seems to me that using those rules (i.e., a "more
|local" name hides a "more remote" name, to generalize the rule to lexical
|scoping as well) is preferable to introducing new required idioms into the
|language.
This requires at least a partial notion of binary operator. which I do not
want to get into because that *really would* be an extension verses what I
am trying to do, which is simply to remove an erroneous special case
restriction.
|Third, although it wasn't mentioned in this rebuttal and only in passing in
|the Koenig/Stroustrup analysis, the fundamental identity between a->b and
|(*a).b is broken by your proposal. Again, I'll have more to say about this
|in the followup to your article in which you specifically addressed this
|issue.
This "fundamental identity" CANNOT be broken by MY proposal, because this
"fundamental identity" is ALREADY broken by operator overloadings already
permitted in the language. Please compile and execute the following on you
own machine and compiler to confirm in fact that the exact "fundamental
identity" you claim above ALREADY fails to exist in C++:
======
#include <iostream.h>
class B
{
public:
void b() { cout << "Tweedledum\n"; }
};
B ab;
class C
{
public:
void b() { cout << "Tweedledee\n"; }
};
C ac;
class A
{
public:
B& operator*() { return ab; }
C* operator->() { return ∾ }
};
main()
{
A a;
a->b();
(*a).b();
return 0;
}
======
|Fourth, the relationship between the infix/prefix/suffix forms of operators
|and the explicit operator notation is broken -- i.e., "a + b" is not
|necessarily the same as "a.operator+(b)" in your proposal. Not only is this
On the contrary, "a + b" CAN be the same -- if the implementor so desires.
If the implementor DOESN'T so desire, then ALREADY
a + b
need not equal
a - -b
so this "problem" ALREADY exists in the current set of overloadable operators.
More to the mark, as noted above (*a).b ALREADY need not be the same as
a->b. Again, all these things are simply left to the good consciousness
or lack thereof of the C++ programmer. Operator. FINALLY ALLOWS C++ progrs
the ability to write a complete consistent SET of operators. It does not
cannot nor should it prevent programmers from the ALREADY existing ability
to write inconsistent sets of operators. This "problem" is nothing new,
but rather a long-standing "feature" of C++.
|feature a potential source of confusion for programmers, it also creates the
|same maintenance nightmare of forwarding functions you mentioned in earlier
|postings.
Only if the programmer doesn't know what he/she is doing, or the programmer
is being deliberately obtuse. But, C++ ALREADY offers ample opportunity to
write bad code. Adding operator.() doesn't add significantly to the
ABILITY of bad programmers to write bad code, but it DOES add significantly
to the ABILITY of good programmers to write good code!
|In summary, while I agree with the desirability of smart references to
|parallel smart pointers, I think that the operator.() mechanism is suspect
|on several grounds, and it doesn't go far enough in providing reference
|semantics. If we had the delegation
If "suspicion" is sufficient reason to block a proposal, then NO proposal
should be accepted. If you have any concrete GROUNDS for your "suspicions"
then state them, and let me address them.
Author: jimad@microsoft.com (Jim Adcock)
Date: 07 Jul 92 02:47:56 GMT Raw View
In article <BqvL5A.Bxz@world.std.com> wmm@world.std.com (William M Miller) writes:
|In article <34.UUL1.3#8618@softrue.UUCP>, Steven Kearns writes:
|> The feedback that I got back was very disappointing, and indicated
|> that the participants did not make any effort to understand the
|> issues.
Agreed. This is my experience too. Committee members are using their
determination NOT to understand as an excuse to block the proposal.
Understanding and finding holes in the proposal WOULD be reason to
shoot it down. What we find instead is that the proposal remains bullet-
proof and committee members use a lack of understanding as their basis
of attack.
|>I was sent an email message that was so vague and mindless
|> that I quickly gave up on responding to it. Clearly, the powers that
|> move the extensions committee are dead set against any proposals
|> (except their own). While this is usually a good policy, the
|> operator dot proposal is different. Unfortunately, the committee
|> members do not appear willing to think about the technical issues.
Again, this is EXACTLY my experience TOO. This gentleman and I have
no relationship except to happen to agree on this issue. Yet our
EXPERIENCES at the hands of certain committee members is identical.
Does this not in at least some small way confirm my complaints about
these committee members? Again, these people simply are not playing
fair, but rather are deliberately playing games to block a valid proposal.
| Stroustrup said the WG discussed Kearns' analysis (92-0021 = N0099) of
| Adcock's proposal to allow overloading operator . (dot) (91-0140 =
| N0073). Stroustrup said the WG decided that the analysis had
| insufficient technical detail and ignored issues raised by Koenig in
| his earlier analysis. Knuttila will send a letter to Kearns asking if
| he'll write a better proposal [sic, I presume this should have read
| "better analysis"].
Again, if there TRULY remain "valid" technical points raised by the K&S
"Analysis" why are not you, K, or S willing to identify such remaining unclarified
points? I have repeated ask such of K, S, or any other contrary committee
member that I could find over the last year, ever point raised in objection
has been countered, yet committee members still persist in this lie that
the K&S points have not been countered. Lie. If there are any such remaining
points raise them again and I will answer them.
|I don't know what was in the "vague and mindless" email message, but the
|minutes seem clear enough. There was very little in the analysis document
|that was not already in Jim's proposal. In particular, there was no attempt
|to deal with the issues raised by the earlier analysis by Koenig and
|Stroustrup.
WHAT valid points were not answered??? Again it is YOU who is unwilling
to engage in substantive debate. If YOU have any unanswer questions,
THEN ASK THEM OF ME. Otherwise discontinue this erroneous claim that
K&S "Analysis" points remain unanswered!
|For example, the key factor that led K&S to explore alternative ways to
|overload operator.() (and apparently mortally offending Jim Adcock in the
|process by expanding the analysis beyond the confines of his specific
|proposal) was the following:
|
| Under Proposal 1 [Jim Adcock's proposal], "r.operator++()" can only
| mean "r.operator.().operator++()". What about "r++"? People expect
| these forms to be equivalent, so making it call
| "Reference::operator++" would surprise them.
This point, like the other points in the K&S "Analysis" is simply in error.
The solution to this "problem" already exists within the language, as I
have previously indicated.
One such simple solution is to simply implement such UNARY operators as
forwarding operators in the smart reference class. Since the set of such
UNARY operators has a VERY small guaranteed upper bound, no one can reasonable
claim that such represents an unworkable "solution" to this "problem" !
|Your analysis did nothing to refute this objection, and it was completely
|silent regarding the alternative approaches K&S suggested, as well as their
|concern about breaking the identity between a->b and (*a).b. Surely an
|analysis that completely ignores the objections raised by earlier commentary
|cannot be regarded as complete? What, then, is the basis for accusing the
|participants of "[not making] any effort to understand the issues" and
|"[being unwilling] to think about the technical issues?" It appears, to
|this observer at least, that the lack of consideration of issues was on your
|part rather than that of the Committee.
BullShit. Since I REPEATEDLY ask the committee members involved in this
dispute EXACTLY WHAT IF ANY ISSUES I had not answered in my mailing to
them, and since THEY refused to answer with ANY SPECIFIC QUESTIONS that they
considered yet unanswered, any "blame" for not answering ANY YET UNANSWERED
QUESTION in their minds falls soley to them.
Again, if any committee member would claim that ANY questions remain
unanswered, then ASK THAT QUESTION and I will answer it!
[BUT please read the postings here first, because I am sure that I and
everyone else is sick to death of seeing the same questions asked over
and over again by people who are unwilling to actually read the previous
answers that I have already posted!]
Author: andrewfg@coral.daisb (Andrew Fitzgibbon)
Date: 7 Jul 92 12:21:14 GMT Raw View
People,
WHY does everybody want overloaded operators? Honestly, it's like kids
with a new toy. We've seen the potential problems with operator.(), the
current ambiguities with operator{->,&,*}().
But we even get ambiguities with operator[] -- surely the easiest of all.
If you have
class SimpleVec {
double * _guts;
int _len;
char magic[200];
public:
The obvious C++ approach is to provide
const double& operator[](int n) const { return _guts[n]; }
double& operator[](int n) { return _guts[n]; }
My preference after three hectic 100,000-line years is to go for
double get(int n) const { return _guts[n]; }
void set(int n, double d) { _guts[n] = d; }
Why? Well first look at a sample `application' of this vector class:
void alter(const SimpleVec& from, SimpleVec * to)
{
to[1] = from[0]; // Wrong, compile error
(*to)[1] = from[0]; // 1
to[0][1] = from[0]; // 2
to->set(1,from.get(0)); // 3
to->set(1,from[0]); // 4
}
Which line do you prefer? I prefer (3)...
o My code always goes to other people.
Looking at (3) says immediately that a function call is happening.
Even if it gets inlined%, people still know that it's something
whose semantics the class implementor has defined.
o My code always goes to other people.
The obvious response to my alter(...) function is to say that the
`to' argument shold be a non-const reference. I disagree -- class
users have been on holiday before, they know that if you give
your address to a stranger, you're asking for trouble.
Calling alter, and giving it the address of the thing that's being
fiddled with allows users' intuitions to begin to work.
Essentially, I'm saying that overloaded operators, while superficially
more intuitive than member functions, are always a recipe for disaster:
Whether it be through a class user's false expectations, the class
implementor's single slip through the equivalence of definitions net, or
plain old efficiency considerations. I feel that if you're calling a
function, however simple, it should look like
[A-Za-z_][A-Za-z_0-9]*(<arg>{,<arg>})
What you see is what you get.
Andrew "Pontificate" FG
--
% Did you know that cfront 3.0 won't inline that call to []() if it occurs
twice in the same expression? Does it piss you off? Can we stop it?
--
Andrew Fitzgibbon, | "If it ain't broke, don't fix it"
Department of Artificial Intelligence, | - traditional (c1950)
Edinburgh University. | "A stitch in time saves nine."
andrewfg@aifh.ed.ac.uk | - traditional (c1590)
Author: jimad@microsoft.com (Jim Adcock)
Date: 06 Jul 92 19:22:10 GMT Raw View
In article <1992Jul2.062332.24947@lth.se> dag@control.lth.se (Dag Bruck) writes:
|Jim's rebuttal has never been distributed to X3J16 members,
I sent it to two members of X3J16 -- the two members who had written the
"Analsis" paper and therefore who were the two most intimately involved,
as far as I could tell.
|neither in paper form in one of the mailings,
It took my first paper a year or so to be distributed, maybe if you wait
another year or two the "Rebuttal" will be distributed too?
|nor in electronic form on the
|extensions mailing list for X3J16.
WHAT EXTENSIONS MAILING LIST ????!!!!
---- I'm sure that a lot of people following this thread on comp.lang.c++
would like to be involved in such an extensions mailing list -- myself
included. Note that I have never seen any mail from such a mailing list
nor been informed of any opportunity to join such a list. Shouldn't this
be part of the "public" access process of the committee, if in fact they
are "OPEN" -- as they claim? Or alternately, what is so "OPEN" about a
private forum for communication that no members of the public can review?
Is perhaps this private mailing list part of the problem????
|I had never seen this text before.
Ask the two members who received this text about that.
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: 8 Jul 92 10:09:40 GMT Raw View
In article <ANDREWFG.92Jul7132114@coral.daisb> andrewfg@coral.daisb (Andrew Fitzgibbon) writes:
>
>People,
>
>WHY does everybody want overloaded operators?
Ever seen a LISP program?
>Honestly, it's like kids
>with a new toy. We've seen the potential problems with operator.(), the
>current ambiguities with operator{->,&,*}().
>
>But we even get ambiguities with operator[] -- surely the easiest of all.
>If you have
>
> class SimpleVec {
> double * _guts;
> int _len;
> char magic[200];
> public:
>
>The obvious C++ approach is to provide
>
> const double& operator[](int n) const { return _guts[n]; }
> double& operator[](int n) { return _guts[n]; }
>
>My preference after three hectic 100,000-line years is to go for
>
> double get(int n) const { return _guts[n]; }
> void set(int n, double d) { _guts[n] = d; }
>
>Why? Well first look at a sample `application' of this vector class:
>
> void alter(const SimpleVec& from, SimpleVec * to)
> {
> to[1] = from[0]; // Wrong, compile error
// Some silly person misdeclared the prototype
// here is the fix
SimpleVec To& *to; // 5a
To[1] = from[0]; // 5b
>
> (*to)[1] = from[0]; // 1
> to[0][1] = from[0]; // 2
>
> to->set(1,from.get(0)); // 3
> to->set(1,from[0]); // 4
> }
>
>Which line do you prefer? I prefer (3)...
I prefer 5.
No, I prefer you get the prototype to this misdeclared
function correct.
Code with operators used judiciously is much easier to
read. Patterns are more easily recognized than names remembered.
You can't misspell an operator, now, can you :-)
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: wmm@world.std.com (William M Miller)
Date: Wed, 8 Jul 1992 04:45:14 GMT Raw View
As I said when I dived into this morass, er, I mean, "discussion," I don't
have the time nor inclination to engage in an extended debate. You can
categorize my decision to cut and run as you will, but I'm going to post
this one more round of replies and then go back to being a lurker. To
reduce the bandwidth, I'm going to collect all my replies into this one
message.
Adcock, <1992Jul06.194509.29976@microsoft.com>:
> You suggest that "smart references" be able to "hook" certain of the
> referenced class's members, implementing them in the "smart reference" class
> instead"
>
>
> smartref.member
>
> meaning SmartRef::member, not Foo::member.
>
> The analogous behavior in the a SmartPtr class would be if a SmartPtr class could
> "hook" a pointed-to class object's member function, implementing that in
> the "smart pointer" class instead:
>
> smartptr->member
>
> meaning SmartPtr::member, not Foo::member
No, there *is* no analogous behavior for smart pointers. This is a major
part of the difference between a (builtin) pointer and a (builtin)
reference: with pointers, you have separate operators for the pointer itself
and the object to which it points, and "->" belongs to the latter group.
With references, *all* operations on the reference apply to the target
object, not the reference itself.
That situation is clearly untenable for smart references, as K&S and Kearns
both pointed out; the issue is where and how to draw the line -- with a
circumlocution, as in your proposal, or with scope rules as is done in
lexical and inheritance name resolution.
Adcock, <1992Jul06.195015.160@microsoft.com>:
> This situation already exists today, in the case of smart pointers:
>
> a->something();
>
> could mean A::something() or it could mean A::operator->() ... something()
No, it couldn't. It's always the latter.
Adcock, <1992Jul06.200912.776@microsoft.com>:
> If you are writing a smart pointer class, does it ever make sense to
> access ITS ordinary members as follows?
>
> smartPtr.doSomething();
>
> -- I'd claim not.
Of course it does. Even the "misuses" of operator->() you cite from
Coplien's book, which you claim should be replaced by operator.(), have a
number of ordinary member functions in the smart pointer/reference class
which must be accessed using the ordinary syntax. As an example, a smart
pointer might be used to implement virtual memory. A typical operation
might be to flush the in-memory copy to backing store and set the "virtual"
bit, which would be done by operations on the smart pointer itself and not
on the pointed-to object, which probably wouldn't know whether it was used
in a VM scheme or not.
Adcock, <1992Jul07.012749.9890@microsoft.com>:
> This "fundamental identity" CANNOT be broken by MY proposal, because this
> "fundamental identity" is ALREADY broken by operator overloadings already
> permitted in the language.
> ...
> A a;
>
> a->b();
> (*a).b();
This has nothing to do with the fundamental identity in question. "a" is
not a pointer, it's a class object with overloaded operators; there are no
guarantees about how any of those operators interact. The issue is "what
does a->b mean when 'a' is a pointer?" If it doesn't mean (*a).b, then
we've lost something. It may be a worthwhile sacrifice, but don't pretend
that nothing's lost.
> |"a + b" is not necessarily the same as "a.operator+(b)" in your proposal
>
> On the contrary, "a + b" CAN be the same
Pardon me, but will you explain the difference between "can be the same" and
"not necessarily the same?" :-)
> |I think that the operator.() mechanism is suspect on several grounds, and
> |it doesn't go far enough in providing reference semantics.
>
> If "suspicion" is sufficient reason to block a proposal, then NO proposal
> should be accepted. If you have any concrete GROUNDS for your "suspicions"
> then state them, and let me address them.
I did, in this very message on which you were commenting. Somehow it
doesn't surprise me much that you weren't impressed...
Kearns, <35.UUL1.3#8618@softrue.UUCP>:
> This is a perfect example of the kind of thinking that has corrupted
> c++. I dont know how many times I have heard "People expect...." to
> justify horribly complicating a C++ rule.
It's true that the "principle of least surprise" is often invoked in
evaluating language proposals; a closely related issue is "consistency with
the existing language." "People expect" new things to work analogously with
existing things in their experience. I had thought the idea that these were
things to strive for in extending the language was a fairly self-evident
concept, but I guess opinions vary on this subject, as well.
> And what justification do you have for saying "people expect
> ..."? Have you done controlled psychological studies?
No; I suppose that would be a reasonable approach, if we could do it
effectively. However, there is at least an existence proof that there are
people who would expect the things mentioned in K&S, since obviously Bjarne
and Andy expected those things (and I make bold to add myself to the list,
as well, for whatever it's worth). A number of the postings on the subject
during this thread have evinced this expectation, as well.
> > Your analysis did nothing to refute this objection
>
> True; although I considered the point in an earlier draft, I considered
> it too obvious to include in the final draft.
That was an unfortunate choice; it left the impression that you were
ignoring, rather than trying to resolve, the issues that caused the earlier
analysis to remain inconclusive, and I think it pretty much completely
accounts for the cool reception your paper received.
> > , and it was completely
> > silent regarding the alternative approaches K&S suggested
>
> the alternative approaches were decisively shown to be inadequate by
> Koenig in his paper. So why should I repeat them?
That's not how I read K&S. Proposal 2 fixed the problem of referential
transparency for operators in proposal 1, but at the expense of requiring
two classes per smart reference. Proposal 3 fixed the two-class problem of
proposal 2, but at the expense of possible unintended hiding of names in the
target class. In other words, each proposal fixed a perceived flaw in its
predecessor. An evaluation of the importance of the various strengths and
weaknesses -- especially establishing some criteria for performing that
evaluation -- would have been a major contribution.
> Your letter is an eloquent illustration of my point. You show that
> you are unaware of some of the most basic C++ philosophical
> underpinnings (i.e. overloaded operators ==> identities do not have
> to hold)
Why do these discussions have to degenerate into ad hominem attacks? I'm
perfectly aware of the fact that overloaded operators are completely
user-defined and bear no necessary relationship either to each other or to
the syntactically-similar built-in operators. The issue is whether adding
smart references to the language must necessarily introduce yet more of
these potential pitfalls or whether we can come up with a way to do so that
is cleaner and more consistent. If there's a way to get smart references
and keep the identities, we should do so; if not, we ought to recognize what
we're giving up and make an informed decision.
> and you complain because I assume that the readers have
> read and understood the previous literature on the subject.
No, I complained because your document appeared to ignore, rather than build
on or refute, the previous analysis. (BTW, though, it is never safe to
assume much of anything about what your audience has read, understood, or
remembers of earlier literature; a brief recapitulation is always
advisable, even if you're simply agreeing with what's been said.)
> Furthermore, you obviously subscribe to the harmfull philosophy of
> trying to make C++ behave as untrained users expect
I'd hardly put Bjarne Stroustrup and Andy Koenig into the category of
"untrained users;" for that matter, I've been programming in C++ since 1986,
so I don't think that I fit that description particularly well, either.
What I'm really trying to do in evaluating language extensions is to keep
the language as predictable as possible. That benefits both neophytes and
experienced users.
Adcock, <1992Jul07.022240.11138@microsoft.com>:
> |You can't possibly be serious about this, that cfront users and suppliers
> |all speak with one voice? Do you have any evidence or even analysis to back
> |up this fantastic claim?
>
> You can't possibly be serious that *I* would speak "in one voice" with
> other people at Microsoft if I had a vote? The issues are EXACTLY the
> same except for naming convention. In one case we say "company" in the
> other case we say "sublicensees"
There's a bit of a difference -- the fact that your company pays your
salary gives them some clout in determining your vote: if you vote against
the company's interests, you could presumably be fired or transferred to
Timbuctu. There is no corresponding threat hanging over the heads of cfront
licensees -- the most USL could do would be to ask "please."
The fact that you responded this way is a positive indication that there is
no evidence to back the AT&T "conspiracy theory."
> The INTENT of Bjarne in writing this that or the other word matter not
> ONE IOTA -- all that matters are the words he DID write, and how reasonable
> C++ programmers interpret those words.
I guess we'll have to agree to disagree here. If something was
inadvertently omitted or garbled in the original ARM text, it seems
eminently reasonable to me to repair it by making the draft read as it would
have if Bjarne had been 100% perfect in putting his words on paper. It only
takes a 50% vote of the Committee to reconsider a feature if the result of
this editorial process is undesirable, so it's no big deal.
> What, ten years from now are people still suppose to be
> calling up Bjarne and asking: "Hey Bjarne, you know page 432 of the ANSI
> C++ Standard, just exactly what did YOU mean by that?" ???!!!
Of course not, that's why the Committee is making the wording as clear as
possible now. That's the major advantage of a committee instead of an
individual writing a standard -- it sure isn't speed! :-)
> | to claim that the current wording
> |is a gratuitous and unjustified change from the base document is simply
> |false, and the vote of the committee to accept the revised wording
> | is an endorsement of that
> |fact.
>
> This statement is simply in error unless you are able to refer to a line
> and a page in a minutes that record this discussion and this vote. You
> and many other C++ committee members have vacuously claimed the truth
> of these statements WITHOUT EVER ONCE being able to point me at any
> minutes where such a discussion and vote were taken. Either show where
> such a discussion and vote are recorded in the minutes, or be quiet and
> retract the changes in the base document.
>
>
> It is FUNDAMENTAL to the process that discussions and votes be recorded
> in the minutes. If you cannot show such, then you have no position to
> argue from.
I don't have easy access to the written copy of the minutes, so I can't give
you a line and page number, but I hope that the following citation from the
minutes will satisfy your request. The wording in question (section 7.1.6,
paragraph 1) first appeared in the draft prepared for the Lund meeting in
June, 1991, document number X3J16/91-0059. According to the minutes there
was no discussion regarding whether the change was substantive, i.e., no one
questioned it. The discussion on the draft occupies about a page of the
minutes (60-70 lines, I didn't count), including discussion of a minor
wording error in the passage in question and whether or not a different
revision was a substantive change, but I've only reproduced the salient
parts in the interest of shortening an already-too-long message. This quote
is from document X3J16/91-0093, if you want to verify it yourself:
Miller pointed out a minor bug in 7.1.6p1. The parenthesized part of
the next to last sentence should read "(which is not a subobject of an
object of a non-ROMABLE type)".
...
Motion by Miller/Druker:
"Move we approve the current Working Paper (91-0059)."
Motion passed: lots yes, 0 no.
As I said, the Committee did approve the draft with the wording under
discussion, and there was opportunity (not taken by anyone present) to
challenge the revision on the grounds that it was a substantive change.
Satisfied?
> If this statement were true then why haven't you nor any other committee
> member been able to refer me to any minutes where such debate and vote
> were recorded ?????
I can't speak for anyone else. This is the first time you've asked me.
> A pointer IS NOT a fundamental type when it is a smart pointer.
This is like saying "A horse is not an animal when it's an automobile." A
"smart pointer" IS NOT A POINTER. (I think there's even a talk at the
upcoming USENIX C++ Conference with that title. :-).
> |Sure. The current draft (section 5.2.4) says, "Thus the expression E1->MOS
> |is the same as (*E1).MOS." That's a flat, unqualified statement.
>
> ERROR ERROR ERROR!
>
> This statement and ALL statements in chapter five are QUALIFIED by the
> second paragraph of the first page of chapter five:
>
> "Relations between operators, such as ++a meaning a+=1, are not
> guaranteed for overloaded operators"
Right, but if the E1 is a pointer, as we were discussing, the "->" is not an
overloaded operator, since you can't overload operators on non-class
objects.
> "." derefences a reference to allow access to a member, just as "->"
> dereferences a pointer to allow access to a member. They do identical
> tasks
Well, that's another one I guess we'll have to agree to disagree about. I'm
afraid I don't find your reasoning about what dot "does" any more persuasive
than you found mine about dot being just a semantic indicator.
> Since
> declared reference merely introduce yet-another name for an existing object,
> the first name of a named declared object must also be a "reference"
Whereas I would reason that a reference is just another name and
conceptually needs no dereferencing, although the common implementation as a
pointer in disguise makes it appear that a dereference is necessary.
Adcock, <1992Jul07.024756.11725@microsoft.com>:
> | In particular, there was no attempt
> |to deal with the issues raised by the earlier analysis by Koenig and
> |Stroustrup.
>
> WHAT valid points were not answered??? Again it is YOU who is unwilling
> to engage in substantive debate. If YOU have any unanswer questions,
> THEN ASK THEM OF ME. Otherwise discontinue this erroneous claim that
> K&S "Analysis" points remain unanswered!
The subject under discussion was what was in Steven Kearns' paper,
X3J16/92-0021, not what you have or haven't said. What I said was that
*that analysis*, commissioned by the Extensions Working Group, did not
explicitly address points from the K&S analysis. What you have or have not
said was irrelevant in addressing why that paper was not warmly received.
Adcock, <1992Jul07.030905.12100@microsoft.com>:
> |1) It requires non-member operators, depending as it does on a conversion
> |from the smart reference type to the target type. It doesn't work if you're
> |trying to define a smart reference to a class that has member operators
> |unless you are able to change the target class.
>...
> This problem only exists if the implementor of the target class engages
> in what is already recognized as being bad programming practice. If the
> implementor of the target class uses such programming practices, then S/HE
> busts C++, not my proposal.
It is generally recognized that operators like operator+=() and the like
should be members, not standalone functions. Operator=(), in fact, is
*required* to be a member. Only binary, commutative operators are generally
preferred to be implemented as standalone functions. You cannot write off
member operators so cavalierly.
> |2) It doesn't address conversion operators, since it would require two
> |user-defined conversions, and the language only gives you one level of
> |implicit application of user-defined conversions.
>
> This is only a problem if users require a large number of conversion
> operators. If, as in the case of any C++ class I have EVER seen, only
> a small finite number of conversions are required, then this remains
> an argument in search of a problem. Excuse me, but NOW *who* isn't being
> serious? [if only a small set of conversions are needed just implement them
> in the smart reference class]
You're still left with the problem of remembering to put a forwarding
function in the smart reference class if you add a conversion operator to
the target class.
----------------------------------------------------------------------
Okay, folks, that wraps it up. To summarize:
1) Nobody's "blocking" action on operator.(). It is still actively under
consideration, along with a number of other proposals, some of which have
higher priority.
2) The ANSI process is as open as practical, consistent with real-world
constraints of making forward progress toward getting a standard within an
acceptable timeframe.
3) My personal position on operator.():
"." is only an operator in the sense that "::" is, i.e., syntactically;
it's not a run-time operation, like all the currently-overloadable
operators are.
A smart-reference proposal based on operator.() doesn't (and can't) give
enough referential transparency; in particular, forwarding functions are
still required for operators (and the undesirability of forwarding
functions was the major impetus for smart references in the first place).
I'll only say more if someone comes up with a really outrageous
misstatement that I feel must be refuted; I think we've pretty much reached
the "IS NOT!" "IS SO!" "IS NOT!" "IS SO!" and personal insult stage in this
discussion.
Ciao.
Author: jimad@microsoft.com (Jim Adcock)
Date: 08 Jul 92 21:00:28 GMT Raw View
In article <ANDREWFG.92Jul7132114@coral.daisb> andrewfg@coral.daisb (Andrew Fitzgibbon) writes:
| to->set(1,from.get(0)); // 3
| to->set(1,from[0]); // 4
| }
|
|Which line do you prefer? I prefer (3)...
|
| o My code always goes to other people.
| Looking at (3) says immediately that a function call is happening.
| Even if it gets inlined%, people still know that it's something
| whose semantics the class implementor has defined.
In a nutshell your position is:
"If everyone would just stop using this annoying plethora of different
syntaxes and all just use MY syntax then there would be no more
confusion and these problems would all go away."
To which I wholeheartedly agree:
If everyone would just stop using this annoying plethora of different
syntaxes and all just use MY syntax then there would be no more
confusion and the problems would all go away.
Unfortunately, some influentual historical types like Kernigham and Ritchie
and Stroustrup didn't like your choice of syntax and instead "invented"
a syntax of their own choosing. How annoying! Because now the rest of
us have to decide between using your syntax and *their* syntax. Unfortunately
*their* syntax is hardwired into their compilers and a few 100 other compilers,
so their syntax is kind of hard to get rid of. Your syntax however isn't
hardwired into the compiler, so we can easily chuck it, which is what
we choose to do. After we have gotten rid of your syntax, the problem
then remains what we should use for *our* syntax. We could invent *our*
own syntax too, but chances are other C++ programmers would just chuck
*our* syntax. What other alternative do we have then? -- We could make
*our* syntax just like the built-in syntax, and then C++ programmers would
be less inclined to chuck *our* syntax -- because even if programmers did
chuck our syntax they'd still be left with the hardwired language syntax
which is identical to ours. So chucking our syntax wouldn't help them
much -- they'd still be stuck with the problem, so that they might as well
bite the bullet and learn the C/C++ syntax once -- at which point in time
they also know *our* syntax. Learning how to solve the problem *once* is
better known by the name of "encapsulation."
This is NOT an operator issue, its an encapsulation issue. The reason
that C++ needs to have overloadable operators and why C++ programmers
need to use them "correctly" is so that other C++ programmers don't
have to keep learning how to solve the same problem over and over and
over again with each new set of libraries, with each new boss, and with
each new company. These issues already HAVE been standardized --
20 years ago by K&R. IF K&R had decided -- like some other well known
languages -- not to have an operator set, but rather just use mnemonic
names for everything, then C++ would not need a complete set of overloadable
operators today. But, if that were the case, how many of us would be using
C++ ??? A large portion of the "win" of C/C++ is in their extensive use
of operators, and the fluidity that those operators gives to our programming
efforts exceeds that of other languages to such an extent that we even
start to stop thinking about these things as even *being* operators, but
rather start thinking about them as being "mere" punctuation within
our programming sentences.
PS:
You seem to be confusing get/set with Query/Put/Get/Set. Follow the
standard ;-)
Author: swillden@news.ccutah.edu (Shawn Willden)
Date: Fri, 10 Jul 92 00:54:34 GMT Raw View
I've been following this debate/flame-war for some time and with
considerable interest (and some amusement :-) ) and I've decided to
jump in, so, here's my $0.02 worth:
I agree with Jim's argument that for the sake of symmetry we should
probably include operator. in the C++ language. The arguments I've
heard *against* operator. (and my responses are):
operator-> and operator. are not a good way to build
SmartPointers and SmartReferences. A better way should
be developed and both constructs should be removed.
I agree, but until a better way is proposed I don't think this matters and
it's essentially irrelevant to the "symmetry" argument in any case. Of
course, we've also heard the argument (which crops up now and again) that
overloadable operators are a Bad Thing in general, in which case I must
say "Find another language."
operator. would require all kinds of hard-to-implement and
confusing name-space searches.
Nonsense, operator. is a UNARY operator. What comes after it doesn't
matter, just like operator-> (I only mention this argument because Jim
has already refuted it so *many* times and some people still seem to
miss it.) operator. is NOT a general forwarding operator. If you still
see a problem with this, just look at it like this:
Given: foo.bar(), translate as follows:
1) Forget the "bar()" ==> foo.bar() == foo.
2) If foo's class has not declared operator.() you already know
how to do this. Use normal member access rules and
go to step 6.
3) . == operator.() ==> foo. == foo.operator.()
4) Suppose foo.operator.() returns a fred&,
foo.operator.() == myfred where myfred is a temporary
that will probably be optimized out of existence.
5) Now we remember the "bar()", so we attach ".bar()" to
"myfred", giving "myfred.bar()", at which point we return
to step 1, replacing "foo" with "myfred" etc.
6) We're done.
Though a general-purpose forwarding operator would be better, I haven't
yet seen a proposal for one. It may be worthwhile to discuss the
possibility, but that's not what we're currently considering.
If I overload operator. I can't access the members of my class
without some awful-looking workaround like (&foo)->bar().
If you want to access your class members then DON'T overload operator.!
("Doctor, when I do that it hurts!" "Then don't DO that!!") As Jim
pointed out, overloading operator. would not affect the ability of member
functions (like operator.() operator&(), etc.) to call OTHER member
functions.
Overloading operator. breaks a fundamental identity we inherit
from C, namely that for a pointer p to a struct, p->foo is
equivalent to (*p).foo.
True. And if I'm not mistaken, operator. would be the first to break
a fundamental identity on a builtin type (a pointer). All of the other
identities (e.g. a++ == a+=1 == a=a+1) still hold for builtin types
though they may break for user-defined types. This is true and seems
to be a problem. Some questions:
1) Why do we consider a pointer a builtin type? Would
it make more sense in C++'s more type-safe world to
say that an int* IS A TYPE in and of itself and that
the declaration of a new type actually creates two
new types, an object type and a pointer type? Thus
declaration of class foo creates type foo* as well
as type foo - meaning the identity no longer applies
because foo* is a user-defined type.
2) Assuming we maintain the position that a pointer is a
pointer is a pointer, type notwithstanding, how important
is this identity? What confusions could arise from
breaking it?
This seems to me to be the most serious objection I've seen.
Philosophically, . is not an operator. Therefore it should not
be overloadable.
Okay... this one doesn't bother me one bit. Should it?
If operator. can be overloaded I will have to look to see
if it has been every time I see something of the form foo.bar.
True. This would be a very serious objection IMHO, if it weren't already
a problem. It would seem to make sense to allow only operators which don't
have a predefined meaning for classes to be overloaded, which would exclude
operator. and operator& as well. operator-> by default means nothing when
applied to a class, so we know that it must be overloaded when we encounter
foo.bar (and know that foo is a class object), likewise when we see foo++,
foo--, foo+=fred, *foo, etc. So this argument indicates that it would
probably be a good idea to remove operator& if we're going to disallow
operator. A counter-argument that some may consider valid is "But foo.bar
is much more common than &foo so it would be more problematic." I can't
say anything about the validity of this claim.
In sum:
It may be a good idea to disallow overloading of operator-> and
operator&. If we don't want to do that, it would seem to make
sense to allow overloading of operator. UNLESS the identity
p->foo == (*p).foo turns out to be an important one AND we assume
that any pointer is a builtin type (that is, that foo* is not
implicitly declared when foo is defined).
Did I miss any of the objections to operator.? Anyone disagree with my
stands on the objections I mentioned?
Shawn Willden
swillden@cc.weber.edu
Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Fri, 3 Jul 1992 02:47:58 GMT Raw View
maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
>In article <12tsi6INNbcl@agate.berkeley.edu> jbuck@forney.berkeley.edu (Joe Buck) writes:
>[Re: Jim Adcocks rebuttal ..]
>
>>is available in online form. It appears to refute every argument I've
>>ever seen against operator.() quite effectively. Is there another
>>argument that hasn't been presented?
>>
> While I lean in favour of overloading operator., I do
>think it is complicated. It is not really analogous to ->
>for two reasons. The first is trivia: pointers are real objects
>in C++, references are not.
However there is a very strong relationship between the two, and it would
seem natural to provide corresponding functionality for both.
> The second I have already posted (no-one commented).
Jim Adcock posted a reply - perhaps you missed it?
[...]
>That is, to resolve operator. requires knowledge of all the members
>of each class is the chain. For operator-> it requires only
>knowledge of the return type of operator->
In fact this is not the case, as Jim explained. His proposal resolves
ambiguity for operator.() in exactly the same way the corresponding ambiguity
for operator->() is handled.
For operator->(), you have to keep looking up the next operator->() for the
returned type until the returned type is a pointer type.
For operator.(), the situation is basically the same, except that you must
keep looking up the next operator.() until the returned class does not have an
operator.()
--
Fergus Henderson fjh@munta.cs.mu.OZ.AU
This .signature VIRUS is a self-referential statement that is true - but
you will only be able to consistently believe it if you copy it to your own
.signature file!
Author: jbn@lulea.trab.se (Johan Bengtsson)
Date: 3 Jul 92 16:05:45 GMT Raw View
cep@taligent.com (Christophe Pettus) writes:
:
: class Base {
: void foo(); // ** public? **
: };
:
: class Reference {
: void foo(); // ** public? **
: private:
: Base& operator.() const;
: };
:
: Reference r;
:
: What does r.foo() do? Does it call Reference::operator.(), and
: returning a Base&, and then call Base::foo(), even though it is
: private?
Access control is applied after scope lookup, so it must be
an access error.
: [...] or is it an error, and you have
: to use something like (&r)->foo() to get at Reference::foo()?
If I understand "Jims Rebuttal" correctly, a correct SmartRef class
overloads operator & to return the corresponding SmartPtr. So
(&r)->foo() will call Base::foo(), maintaining the C identity
x.y === (&x)->y
Jim's solution instead seems to be to overload
Reference::operator->():
Reference* Reference::operator->() { return this; }
Amazingly, this makes it possible to call Reference::foo(), by
using r->foo(). It does have some symmetry with SmartPtrs, you
use the "unusual" operator (. or ->) to access the smart-members.
--
--------------------------------------------------------------------------
| Johan Bengtsson, Telia Research AB, Aurorum 6, S-951 75 Lulea, Sweden |
| Johan.Bengtsson@lulea.trab.se; Voice:(+46)92075471; Fax:(+46)92075490 |
--------------------------------------------------------------------------
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Sat, 4 Jul 1992 06:04:36 GMT Raw View
In article <Bqs38H.4L9@taligent.com> cep@taligent.com (Christophe Pettus) writes:
>
>I would claim that in real-world cases, the inability to directly
>access members of classes that have declared an operator.() without
>going through the (&r)->foo() hack is at best ugly, at worst a serious
>problem.
No. You would put operator. in classes DESIGNED to be
reference classes. The user would not want to call any members
of the class (it is SUPPOSED to be transparent).
And as Jim pointed out, if you REALLY want to play
with the reference class, you can just overload operator->
for that purpose. Something like
class Ref {
foo();
X operator.();
Ref* operator->(){return this;}
};
Ref r;
r->foo();
>Looking through a large body of code I've written along these
>lines tends to confirm it. I have difficulty with the basic idea of
>considering . an operator at all, any more than I would like the
>language to allow you to override operator::(), whatever that might
>do.
Exactly right. You can use reference classes as if
they did not exist, only the class they refer to appears visible
to the user. The fact that this can be made to work properly
is an argument FOR operator., not against it.
>--
>-- Christophe
>
>"Be calm. Look cute."
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Sat, 4 Jul 1992 06:14:17 GMT Raw View
In article <1992Jul2.212547.897@murdoch.acc.Virginia.EDU> gs4t@Virginia.EDU (Gnanasekaran Swaminathan) writes:
>cep@taligent.com (Christophe Pettus) writes:
>
>I agree. The x3j16 should not succumb to any pressure from anybody.
But the SHOULD yield to proper argument.
>
>operator.() also has the following readability problem which
>operator->() does not have:
Watch out: I am about to reverse your argument!
>
>Suppose some code has the following fragment:
>
[bit here deliberately omitted]
> a->something(); I don't have to look into class A to figure
> out that class A has operator -> ()
But it s confusing because I see -> and don't knwo
whether 'a' is a class object or a pointer.
> a.something(); If operator.() is allowed, I have to look into the
> class A to find out whether it is A::something()
> or A::operator.(). ... something(), thereby
> hindering the readability of the program heavily.
But this is not confusing: 'a' is definitely a class object.
>
>-Sekar
>
The fact that you can't tell whether 'something' is
a member of 'A' or not is called 'transparency'. It may well
be considered a desirable feature of operator.
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: wmm@world.std.com (William M Miller)
Date: Sat, 4 Jul 1992 17:38:30 GMT Raw View
In article <1992Jul02.000036.3980@microsoft.com>, Jim Adcock writes:
> Below find a copy of a "Rebuttal" I sent to Koenig and Stroustrup last
> year in response to their "Analysis" paper. I haven't posted this note
> to comp.lang.c++ before because Stroustrup stenuously objected to this
> "Rebuttal."
I'll leave it to Bjarne or you to talk about his objections to your
rebuttal, since anything I said on that subject would be only speculation.
I basically have two reactions:
1) I think you've done a good job of supporting the need for smart
references.
2) I'm as unconvinced as ever, perhaps more so, that operator.() is the
right way to go about adding smart references to the language.
I have the following objections to your proposal (not in priority order):
First, I do not believe that "." is an operator in the same sense as the
currently overloadable operators; I'll say more about this in a followup to
the article in which you specifically asked about this issue.
Second, a circumlocution is required to access members of the smart
reference object. In your paper, as I recall, you suggest
( &smart_ref ) -> member
as the workaround. Another possibility was suggested in the
Koenig/Stroustrup paper, namely putting all the members requiring access
into a base class and just having the operator.() in the derived class; this
style would allow access to the members by casting the smart reference
object to a reference to the base class.
I think the necessity of these circumlocutions detracts from your proposal.
We have a perfectly good set of scope rules that handle similar sorts of
things in inheritance; it seems to me that using those rules (i.e., a "more
local" name hides a "more remote" name, to generalize the rule to lexical
scoping as well) is preferable to introducing new required idioms into the
language.
Third, although it wasn't mentioned in this rebuttal and only in passing in
the Koenig/Stroustrup analysis, the fundamental identity between a->b and
(*a).b is broken by your proposal. Again, I'll have more to say about this
in the followup to your article in which you specifically addressed this
issue.
Fourth, the relationship between the infix/prefix/suffix forms of operators
and the explicit operator notation is broken -- i.e., "a + b" is not
necessarily the same as "a.operator+(b)" in your proposal. Not only is this
feature a potential source of confusion for programmers, it also creates the
same maintenance nightmare of forwarding functions you mentioned in earlier
postings.
In summary, while I agree with the desirability of smart references to
parallel smart pointers, I think that the operator.() mechanism is suspect
on several grounds, and it doesn't go far enough in providing reference
semantics. If we had the delegation feature from the original conception of
multiple inheritance, that would address all my concerns. It was reported
to be problematic, however, so I don't know what to suggest as an
alternative. I'd be very interested either in analysis of the problems
encountered with delegation or in a smart reference proposal that does not
have the difficulties I listed above.
Author: wmm@world.std.com (William M Miller)
Date: Sat, 4 Jul 1992 17:41:34 GMT Raw View
In article <34.UUL1.3#8618@softrue.UUCP>, Steven Kearns writes:
> I was responsible for evaluating the operator . proposal, and I
> prepared a paper for the London meeting, which I could not attend.
> The paper evaluated the proposal positively.
>
> The feedback that I got back was very disappointing, and indicated
> that the participants did not make any effort to understand the
> issues. I was sent an email message that was so vague and mindless
> that I quickly gave up on responding to it. Clearly, the powers that
> move the extensions committee are dead set against any proposals
> (except their own). While this is usually a good policy, the
> operator dot proposal is different. Unfortunately, the committee
> members do not appear willing to think about the technical issues.
I also was not at the London meeting, so all I have to go on is the official
minutes, which read:
Stroustrup said the WG discussed Kearns' analysis (92-0021 = N0099) of
Adcock's proposal to allow overloading operator . (dot) (91-0140 =
N0073). Stroustrup said the WG decided that the analysis had
insufficient technical detail and ignored issues raised by Koenig in
his earlier analysis. Knuttila will send a letter to Kearns asking if
he'll write a better proposal [sic, I presume this should have read
"better analysis"].
I don't know what was in the "vague and mindless" email message, but the
minutes seem clear enough. There was very little in the analysis document
that was not already in Jim's proposal. In particular, there was no attempt
to deal with the issues raised by the earlier analysis by Koenig and
Stroustrup.
For example, the key factor that led K&S to explore alternative ways to
overload operator.() (and apparently mortally offending Jim Adcock in the
process by expanding the analysis beyond the confines of his specific
proposal) was the following:
Under Proposal 1 [Jim Adcock's proposal], "r.operator++()" can only
mean "r.operator.().operator++()". What about "r++"? People expect
these forms to be equivalent, so making it call
"Reference::operator++" would surprise them.
Your analysis did nothing to refute this objection, and it was completely
silent regarding the alternative approaches K&S suggested, as well as their
concern about breaking the identity between a->b and (*a).b. Surely an
analysis that completely ignores the objections raised by earlier commentary
cannot be regarded as complete? What, then, is the basis for accusing the
participants of "[not making] any effort to understand the issues" and
"[being unwilling] to think about the technical issues?" It appears, to
this observer at least, that the lack of consideration of issues was on your
part rather than that of the Committee.
Author: amewaldu@cayley.waterloo.edu (Andrew Walduck)
Date: Sat, 4 Jul 1992 20:29:52 GMT Raw View
In article <BqvL07.BsF@world.std.com> wmm@world.std.com (William M Miller) writes:
>as the workaround. Another possibility was suggested in the
>Koenig/Stroustrup paper, namely putting all the members requiring access
>into a base class and just having the operator.() in the derived class; this
>style would allow access to the members by casting the smart reference
>object to a reference to the base class.
IMHO, casting objects around is a BAD THING(tm).
>Third, although it wasn't mentioned in this rebuttal and only in passing in
>the Koenig/Stroustrup analysis, the fundamental identity between a->b and
>(*a).b is broken by your proposal. Again, I'll have more to say about this
>in the followup to your article in which you specifically addressed this
>issue.
Ah...but isn't the fundamental identity between
a = a + b; and a += b; already broken in C++...
Or (as a better case) a += 1, and a++, due to the overloadable operators??
I don't think this is a problem. It is up to the designer of the class
to decide if a->b and (*a).b are to be the same operation.
This "brokeness" is not new...it is already alive and well in C++ ;-)
>Fourth, the relationship between the infix/prefix/suffix forms of operators
>and the explicit operator notation is broken -- i.e., "a + b" is not
>necessarily the same as "a.operator+(b)" in your proposal. Not only is this
>feature a potential source of confusion for programmers, it also creates the
>same maintenance nightmare of forwarding functions you mentioned in earlier
>postings.
But isn't this already the case in C++??
Ie: a += 1 does not equal a++ does not equal ++a (depending on how the
operators are overloaded..)
Andrew
Author: ian@syacus.acus.oz.au (Ian Joyner)
Date: Mon, 6 Jul 1992 01:47:12 GMT Raw View
I have been watching this argument with interest, and some mild amusement.
It seems Jim is asking for both the '->' and '.' operators to be
made consistent. After all they are both 'member access' operators.
The only difference is that if you declare an object:
a_class object;
then you must use '.'. If you declare it:
a_class* object;
then you must use '->'. This as I pointed out in my critique gives
rise to an artifical distinction which results in such language
irregularities as Jim has pointed out. Having said that, I am not
so sure that it is a good idea to overload such operators as
'->' and '.'. But surely they should at least be consistent. In fact
so consistent that the programmer has one member access operator, and the
trivial decision whether to dereference or not is left to the compiler.
But then I suspect the number of irregularites present in C++ will keep
such time and patience consuming arguments going for a long time.
--
Ian Joyner ACUS (Australian Centre for Unisys Software) ian@syacus.acus.oz
"Where is the man with all the great directions?...You can't imagine it,
how hard it is to grow, Can you imagine the order of the universe?" ABWH
Disclaimer:Opinions and comments are personal.
Author: dag@control.lth.se (Dag Bruck)
Date: Tue, 30 Jun 1992 15:07:23 GMT Raw View
First of all note that I have changed the subject line. The handling
of the operator . proposal is not characterized by speed, and even if
it is correct, we have failed at a human level to handle this
situation as well as we should.
In <comp.lang.c++,comp.object> jimad@microsoft.com (Jim Adcock) writes:
>
>Let me cast no aspersions on this fact. Committee members HAVE NOT
>"done as good job as humanly possible under the circumstances."
> ....
>On the contrary, my treatment by certain committee members over the
>last two years has been nothing but insults, which is why I complain
>publicly now.
>
>[Other committee members have been reasonable, honest, friendly, and
> helpful. Unfortunately, they are not the people involved in this issue]
Jim Adcock is not satisfied with the treatment by certain members of
X3J16, which I assume includes myself. Luckily, there seems to be
people on the committee that Jim has had a good collaboration with.
I suggest that Jim tries to develop his proposal with the help from
these people, and in this case I also mean making it better presented
for the rest of the committee. There are about 40 people who seem to
attend most meetings, and I suppose at least a few are in the "good"
category.
I is also worth pointing out that I have just a single vote, and that
Andrew Koenig and Bjarne Stroustrup have none. Even if I'm not
satisfied, the committee could very well vote, and my vote would not
matter much.
There does not seem to much point in continuing this argument between
Jim Adcock and myself. I have suggested that he starts commenting on
the available analysis papers. That may not be very constructive, but
it's my standpoint. [Proverb: the horizon of many people is a circle
of radius zero, and that is what they call their standpoint.]
>Last time I checked ANSI was SUPPOSE to be "OPEN" on an INDIVIDUAL basis,
>whereas it's ISO that works on a company basis. Perhaps some ANSI members
>are confused on this issue?
ANSI X3J16 is open to companies and individuals, but if you're
employed by a company represented on the committee, only one
representative for your company can vote. Furthermore, mailings are
sent to only one person representing the company, and that person is
responsible for redistributing the documents to other members employed
by that company.
Representation to ISO WG21 is by nation. Each country sends a
delegation, which in most cases consists of one person. In any case,
each country has only one vote.
All of this has been explained in greater detail before.
Author: kearns@softrue.UUCP (Steven Kearns)
Date: Tue, 30 Jun 92 20:41:11 PDT Raw View
> From: dag@control.lth.se (Dag Bruck)
> Subject: Handling of operator . proposal
>
> First of all note that I have changed the subject line. The handling
> of the operator . proposal is not characterized by speed, and even if
> it is correct, we have failed at a human level to handle this
> situation as well as we should.
>
I was responsible for evaluating the operator . proposal, and I
prepared a paper for the London meeting, which I could not attend.
The paper evaluated the proposal positively.
The feedback that I got back was very disappointing, and indicated
that the participants did not make any effort to understand the
issues. I was sent an email message that was so vague and mindless
that I quickly gave up on responding to it. Clearly, the powers that
move the extensions committee are dead set against any proposals
(except their own). While this is usually a good policy, the
operator dot proposal is different. Unfortunately, the committee
members do not appear willing to think about the technical issues.
-steve
********************************************************
* Steven Kearns ....uunet!softrue!kearns *
* Software Truth softrue!kearns@uunet.uu.net *
********************************************************
Author: jbuck@forney.berkeley.edu (Joe Buck)
Date: 2 Jul 1992 03:18:30 GMT Raw View
In article <1992Jul02.000036.3980@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>Below find a copy of a "Rebuttal" I sent to Koenig and Stroustrup last
>year in response to their "Analysis" paper.
Wow. Given this refutation, I can't imagine any ANSI committee member
arguing that Jim hasn't made his case and met the objections, unless
they haven't seen it and haven't been following the discussion, or
are otherwise confused about the proposal, which is to make operator.()
work exactly the same way operator->() does.
>I haven't posted this note
>to comp.lang.c++ before because Stroustrup strenuously objected to this
>"Rebuttal."
I am interested in reading Stroustrup's response to this rebuttal, if it
is available in online form. It appears to refute every argument I've
ever seen against operator.() quite effectively. Is there another
argument that hasn't been presented?
--
Joe Buck jbuck@ohm.berkeley.edu
Author: dag@control.lth.se (Dag Bruck)
Date: 2 Jul 92 06:23:32 GMT Raw View
In <comp.lang.c++,comp.std.c++> jbuck@forney.berkeley.edu (Joe Buck) writes:
>In article <1992Jul02.000036.3980@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>>Below find a copy of a "Rebuttal" I sent to Koenig and Stroustrup last
>>year in response to their "Analysis" paper.
>
>Wow. Given this refutation, I can't imagine any ANSI committee member
>arguing that Jim hasn't made his case and met the objections, unless
>they haven't seen it and haven't been following the discussion, or
>are otherwise confused about the proposal, which is to make operator.()
>work exactly the same way operator->() does.
Jim's rebuttal has never been distributed to X3J16 members, neither in
paper form in one of the mailings, nor in electronic form on the
extensions mailing list for X3J16. I had never seen this text before.
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Thu, 2 Jul 1992 08:41:13 GMT Raw View
In article <12tsi6INNbcl@agate.berkeley.edu> jbuck@forney.berkeley.edu (Joe Buck) writes:
[Re: Jim Adcocks rebuttal ..]
>is available in online form. It appears to refute every argument I've
>ever seen against operator.() quite effectively. Is there another
>argument that hasn't been presented?
>
While I lean in favour of overloading operator., I do
think it is complicated. It is not really analogous to ->
for two reasons. The first is trivia: pointers are real objects
in C++, references are not.
The second I have already posted (no-one commented).
Consider a->b, either a is a class or a pointer. If a class,
operator-> must be overloaded (else error), it returns
either a pointer (we are finished) or another class (repeat).
When you get the pointer, it binds to b.
For operator. it is much more complicated.
Consider
class X {
Y operator.() {}
member();
};
X x;
x.member();
It cannot be determined whether the last line binds to X::member,
to Y::member, is ambiguous, or whatever without full knowledge
of Y and so on (through the overloaded operator. chain)
That is, to resolve operator. requires knowledge of all the members
of each class is the chain. For operator-> it requires only
knowledge of the return type of operator->
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: jbuck@forney.berkeley.edu (Joe Buck)
Date: 2 Jul 1992 18:25:58 GMT Raw View
In article <1992Jul2.084113.16132@ucc.su.OZ.AU> maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller) writes:
> For operator. it is much more complicated.
>Consider
> class X {
> Y operator.() {}
> member();
> };
> X x;
>
> x.member();
>
>It cannot be determined whether the last line binds to X::member,
>to Y::member, is ambiguous, or whatever without full knowledge
>of Y and so on (through the overloaded operator. chain)
You did not read Jim's rebuttal, where he answered this point directly.
There is absolutely no ambiguity. If operator. is defined, as soon as the
. is seen, operator.() is ALWAYS used. No matter what.
>That is, to resolve operator. requires knowledge of all the members
>of each class is the chain. For operator-> it requires only
>knowledge of the return type of operator->
No, it doesn't! You are responding to your incorrect interpretation of
Jim's proposal, and not his proposal. The only way to call X::member
is through "->", since all calls using "." will use operator.().
That is,
x.member()
will call member() on whatever is returned by operator.(). If the
thing that is returned by operator. doesn't have a member() member
function, you have an error which is detected by the compiler. No
lookahead is required to parse this thing or to choose what operator
to invoke.
--
Joe Buck jbuck@ohm.berkeley.edu
Author: maxtal@extro.ucc.su.OZ.AU (John (MAX) Skaller)
Date: Thu, 2 Jul 1992 17:59:11 GMT Raw View
In article <1992Jul2.062332.24947@lth.se> dag@control.lth.se (Dag Bruck) writes:
>In <comp.lang.c++,comp.std.c++> jbuck@forney.berkeley.edu (Joe Buck) writes:
>>In article <1992Jul02.000036.3980@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>>>Below find a copy of a "Rebuttal" I sent to Koenig and Stroustrup last
>>>year in response to their "Analysis" paper.
>>
>>Wow. Given this refutation, I can't imagine any ANSI committee member
>>arguing that Jim hasn't made his case and met the objections, unless
>>they haven't seen it and haven't been following the discussion, or
>>are otherwise confused about the proposal, which is to make operator.()
>>work exactly the same way operator->() does.
>
>Jim's rebuttal has never been distributed to X3J16 members, neither in
>paper form in one of the mailings, nor in electronic form on the
>extensions mailing list for X3J16. I had never seen this text before.
IS THIS NOT A PERFECTLY GOOD REASON TO SUPPORT FORMATION
OF A NEWSGROUP FOR SUCH PURPOSES?
Please support formation of comp.iso.c++.
More comments are required.
[Help? anyone familiar with how to form a new, moderated
newgroup?]
--
;----------------------------------------------------------------------
JOHN (MAX) SKALLER, maxtal@extro.ucc.su.oz.au
Maxtal Pty Ltd, 6 MacKay St ASHFIELD, NSW 2131, AUSTRALIA
;--------------- SCIENTIFIC AND ENGINEERING SOFTWARE ------------------
Author: cep@taligent.com (Christophe Pettus)
Date: Thu, 2 Jul 1992 20:21:53 GMT Raw View
In article <1992Jul02.000036.3980@microsoft.com> jimad@microsoft.com (Jim Adcock
) writes:
>Thus, I continue to insist that operator.() should be overloadable, that
>proposal #1 is the way to go, and that the committee should stop futzing
>around and put it into the language before much more confusing mixed
>syntax code is forced to be written by this needless and destructive
>restriction. Let's stop keeping C++ programmers from expressing their
>forwarding operations using correct syntax! Remove the needless and
>erroneous special case restriction now!
Given this example:
class Base {
void foo();
};
class Reference {
void foo();
private:
Base& operator.() const;
};
Reference r;
What does r.foo() do? Does it call Reference::operator.(), and
returning a Base&, and then call Base::foo(), even though it is
private? Or does it call Reference::foo(), since
Reference::operator.() is inaccesible (note that this is a violation of
the C++ semantics for access control), or is it an error, and you have
to use something like (&r)->foo() to get at Reference::foo()?
I would claim that in real-world cases, the inability to directly
access members of classes that have declared an operator.() without
going through the (&r)->foo() hack is at best ugly, at worst a serious
problem. Looking through a large body of code I've written along these
lines tends to confirm it. I have difficulty with the basic idea of
considering . an operator at all, any more than I would like the
language to allow you to override operator::(), whatever that might
do.
--
-- Christophe
"Be calm. Look cute."
Author: gs4t@Virginia.EDU (Gnanasekaran Swaminathan)
Date: Thu, 2 Jul 1992 21:25:47 GMT Raw View
cep@taligent.com (Christophe Pettus) writes:
> I would claim that in real-world cases, the inability to directly
> access members of classes that have declared an operator.() without
> going through the (&r)->foo() hack is at best ugly, at worst a serious
> problem. Looking through a large body of code I've written along these
> lines tends to confirm it. I have difficulty with the basic idea of
> considering . an operator at all, any more than I would like the
> language to allow you to override operator::(), whatever that might
> do.
I agree. The x3j16 should not succumb to any pressure from anybody.
operator.() also has the following readability problem which
operator->() does not have:
Suppose some code has the following fragment:
A a;
a->something(); I don't have to look into class A to figure
out that class A has operator -> ()
a.something(); If operator.() is allowed, I have to look into the
class A to find out whether it is A::something()
or A::operator.(). ... something(), thereby
hindering the readability of the program heavily.
-Sekar