Topic: Agreeing on our disagreement: operator.()


Author: jimad@microsoft.com (Jim Adcock)
Date: 10 Jul 92 20:10:38 GMT
Raw View
In article <9219221.2002@mulga.cs.mu.OZ.AU> fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
|The ambiguity is easily resolved by giving precedence to (2), or equivalently
|by changing (1) to
|
|     (1) a reference to a class for which operator.() is not defined.

Agreed, this wording helps clarify the oft-stated intent even more.

| Please don't let Jim's bad manners stop you from considering
|operator.(). This proposal is too good to let personality clashes prevent it
|from being accepted.

My manners were a lot better two years and several thousand exchanges ago.
I encourage any other supporters of this idea to try to make your points to
the committee members and see if their attitude towards this subject doesn't
sour your temper too.  I am not the only person who has complained
of being ill-treated on this subject.




Author: mat@mole-end
Date: Wed, 8 Jul 1992 15:55:35 GMT
Raw View
In article <Br1zvI.Hzn@world.std.com>, wmm@world.std.com (William M Miller) writes:
> As I said when I dived into this morass, er, I mean, "discussion," I don't
> 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.

Let's see if we can get a little convergence.

> > 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.

Does the proposed  operator.()  REPLACE the built-in  operator.()  or
SUPPLEMENT the built-in  operator.() ?

I think that implicit in Jim's view of the world (and of his proposal)
is that the overload would supplement the built-in operator, expanding
the name space searched for a name; implicit in William Miller's view
(and the view of others) is that the overloaded operator.() would
replace the built-in operator.

Do we agree that this is our (first) disagreement?  I think that we can
answer this with a `yes' or `no.'  If `yes,' we can then (and only then)
begin to discuss whether the behaviors are reasonable.
--
 (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: 09 Jul 92 20:58:13 GMT
Raw View
In article <1992Jul8.155535.5979@mole-end> mat@mole-end writes:
|Does the proposed  operator.()  REPLACE the built-in  operator.()  or
|SUPPLEMENT the built-in  operator.() ?
|
|I think that implicit in Jim's view of the world (and of his proposal)
|is that the overload would supplement the built-in operator, expanding
|the name space searched for a name; implicit in William Miller's view
|(and the view of others) is that the overloaded operator.() would
|replace the built-in operator.
|
|Do we agree that this is our (first) disagreement?  I think that we can
|answer this with a `yes' or `no.'  If `yes,' we can then (and only then)
|begin to discuss whether the behaviors are reasonable.

I agree that this issue continues to be a major source of misunderstanding,
BUT either I misunderstand your statement of my position above, or else
I do understand and I disagree with your statement of my position above.

The only things implicit in my proposal before the committee is that I
MEANT what I said, and anything I DIDN'T say I DIDN'T mean, and also
implicit in my proposal was the assumption that people reading the
proposal had used operator->(), understood what it does and how it
works.  Based on this second, apparently incorrect assumption, I suggested
that operator.() should work analogously to operator->().  Unfortunately
for me, this assumed people know what an analogy is, know how to make
an analogy, and are WILLING to make an analogy.  I also assumed that
if people considered ARM a SUFFICIENT basis for specifying how
operator->() works that then these SAME people would consider an
equivalent specification of operator.() SUFFICIENT for their understanding.
I assumed this, because the alternative point of view would have to be
that the committee members involved in the standardization effort
DO NOT consider the base specification documents sufficient to
document how C++ "really works" but rather are implicitly relying on
one or another vendor's implementation to specify how C++ "really works."
Since such a standardization effort implicitly standardizing on
one or another vendor's implementation, rather than on the base documents,
could not possibly answer valid "test" questions put forth to an
eventual "standing C++ committee" after C++ has been standardize --
analogous to the current "standing C committee" which attempts to answer
questions about the "C" standard -- I thus concluded that committee members
would have to consider a specification of operator.() identical to the
base documents specification of operator->() would be sufficient
documentation for them to understand my proposal.  Conversely, if
they cannot understand my proposal it means that they cannot understand
operator->() based on their OWN base documents -- to which I can only
suggest that they then ought to improve their own base documents discription
of operator->() -- in which case I will be happy to update my discription
of how operator.() works to match their description of how operator->()
works.  I decline to specify for them how they think the base documents
descriptions of operator->() should be improved, since they may consider
their current description of operator->() to be wholey adequate -- in
which case my current description of operator.() must also be wholey
adequate since the documentation in each case is for all practical
purposes IDENTICAL.

MY own understanding of how operator->() works is as follows, based on personal experiences with several different C++ compilers:

Given:

 x -> m

If x is not an object of class type or a reference to an object of class
type, then this issue all defaults to the built-in behavior.

If x IS an object of class type or a reference to an object of class
type that doesn't have an overloaded operator->() -- either directly
or via inheritence from a superclass [ARM page 306] then this issue
all defaults to the built-in behavior.

If x IS an object of class type or a reference to an object of class
type that DOES have an overloaded operator->() -- either directly
or via inheritence from a superclass [ARM page 306] then the
original statement becomes via compiler substitution IDENTICAL
to the following situation:

 (x.operator->()) -> m

[ARM page 337]

where the dot in the ARM description must mean the same thing as
"built-in dot" since the ARM description predates overloadable
operator dot.  [Note that the above substitution is a "psuedo-code"
description for the actual code that a given compiler emits --
it does not "literally" perform this textual substitution.]

So where is there any issue of "Name Space Seaching" or "Name Space
Extension" or whatever in operator->() ???? I can see no such thing.
The behavior of overloadable operator->() IN NO WAY WHATSOEVER depends
on the RHS -- the name space of "m" simply NEVER enters the question.
The problem is identically the same as if someone had written:

 (x.operator_arrow()) -> m

[except of course "operator_arrow" is in user name space not implementation
 name space]

The only other source of confusing about operator->() is that --
somewhat surprisingly -- operator->() is defined to be multiply
forwarding: if it returns an object or reference of class type,
then the operator->() for that class etc etc are invoked.

Does everyone now REALLY understand how operator->() works? --
because if you do not, then please don't read the below description
of operator.() -- because you will only continue to confuse yourself
and others on the net or in the committee!

Disclaimer:  Please DO NOT read the below until you REALLY understand
how overloadable operator->() works!

======  HOW OPERATOR DOT REALLY WORKS: ======

overloadable operator.() really Really REALLY does work IDENTICALLY
to overloadable operator->() except for the following differences:

1) The invoking token for overloadable operator->() is "->" whereas the
invoking token for overloadable operator.() is "."

2) The return type for overloadable operator->() must be either a pointer
to a class or an object of or a reference to a class for which operator->()
is defined [in which case that operator will in turn be invoked]
Whereas the return type for overloadable operator.() must be
either a reference to a class or an object of or a reference to a class
for which operator.() is defined [in which case that operator will in
turn be invoked]

======

That's All Folks!

That's what *I* said, and that's what *I* meant.  No more, no less.

If you've ever implemented a compiler that supports overloadable
operator->() then you already KNOW what it takes to implement operator.()

If you've ever written a program that uses overloadable
operator->() then you already KNOW how to use operator.()

The issues are IDENTICAL.





Author: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Date: Fri, 10 Jul 1992 11:39:25 GMT
Raw View
jimad@microsoft.com (Jim Adcock) writes:

>overloadable operator.() really Really REALLY does work IDENTICALLY
>to overloadable operator->() except for the following differences:
>
>1) The invoking token for overloadable operator->() is "->" whereas the
>invoking token for overloadable operator.() is "."
>
>2) The return type for overloadable operator->() must be either a pointer
>to a class or an object of or a reference to a class for which operator->()
>is defined [in which case that operator will in turn be invoked]
>Whereas the return type for overloadable operator.() must be
>either a reference to a class or an object of or a reference to a class
>for which operator.() is defined [in which case that operator will in
>turn be invoked]

There is one slight ambiguity in the above, easily resolved, which I believe
has mat@mole-end and others confused. When you say (the following edited for
clarity)

> The return type for overloadable operator.() must be either
>     (1) a reference to a class, or
>     (2) an object of or a reference to a class for which operator.() is
>         defined [in which case that operator will in turn be invoked]

the ambiguity is that sets (1) and (2) are not disjoint. That is, a
reference to a class for which operator.() is defined falls in both (1) and (2).
The ambiguity is easily resolved by giving precedence to (2), or equivalently
by changing (1) to

     (1) a reference to a class for which operator.() is not defined.

So to answer mat@mole-end's question,

mat> Does the proposed  operator.()  REPLACE the built-in  operator.()  or
mat> SUPPLEMENT the built-in  operator.() ?

operator.() will "replace" rather than supplement the built-in operator.().
Ie. if operator.() is defined for class X, then
 X x; x.foo()
will *always* mean x.operator.().foo.

P.S.
 Please don't let Jim's bad manners stop you from considering
operator.(). This proposal is too good to let personality clashes prevent it
from being accepted.

--
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!