[comp.std.c++] operator. and ideas for extensions in general

bs@alice.UUCP (Bjarne Stroustrup) (09/25/90)

I am tempted to post this on comp.lang.c++ and comp.lang.std. Comments


How one might overload operator . (dot).

Note that overloading of an operator in C++ is triggered by the use
of a class object in a place where a class object would otherwise
be illegal (the exceptions are operators "=" "," and unary "&" where
the use for a class object operand is predefined where the user
doesn't define a meaning). Thus overloading of -> is triggered
by using an object of class type as the left hand argument A->M.

Note that `M' is not used in this overloading. Operator-> is for
overloading purposes considered a unary operator operating on its
left hand operand. C++, like C, requires that the right hand operand
of -> be a name and that name be a member of the class identified
by the type of the left hand operand of ->. The result of evaluating
operator->() is used as the pointer denoting the object from which
M is selected, thus A->M means A.operator->().M .

Now consider operator ".": For every object A of class type A.M is
defined to mean select the member M from A's class. This implies
that IF we wanted to overload it it would have to belong to the
group of operators where its user-defined meaning replaces its
predefined meaning. In parallel with operator "->" it would also
appear sensible to consider "." a unary operator operating on its
left hand operand (for overloading purposes).

This would imply:

	struct X {
		int m;
	};

	class RX {
		S* p;
	public:
		// ...
		X& operator.() { return *p; }
	};

	void f(RX r)
	{
		r.m = 7;	// (r.operator.()).m = 7
				// *(r.p) = 7
	}

Note that this would not be affected by RX having a member `m'
since the definition of operator.() would completely supercede
the predefined meaning. Objects of class RX would have to be
manipulated through pointers.

Note that implementing this scheme would not break any existing code.
It is an extension that preserves source and link compatibility.

*******

Now. A campaign for the introduction of operator.() into C++ has
been suggested. I am not about to join it, but I'll use operator.()
as an example of how one might go about getting a new feature
into C++.

Basically, you send a letter to the ANSI C++ committee (X3J16);
a note on the net will not do even though many committee members
will read it. Most of us are busy and would in most cases find it
MUCH easier to forget about the idea.

Once at the committee your suggestion will be given to some working
group to look at. The ones most likely for suggestions are:

	core language
	extensions
	libraries

In the case of operator.() it would be the extension working group
(chair: Bjarne Stroustrup).

What would such a working group look at in a proposal?:


(1) Is it precise? (can we understand what you are suggesting?)
	The discussion of operator.() above isn't precise.
	It hints at things but does not refer to relevant parts
	of the ARM nor is it framed in an approximation of the
	language used in the ARM.

(2) Why is the extension needed?
	The discussion above leaves the reader guessing. There has
	been discussions of `why?' on this newsgroup but you cannot
	assume that the committee members have read or understood
	them. Remember: there will be someone looking to reject the
	proposal; if noone else a tired compiler writer or an over-
	worked tutorial writer. We don't want a language that is
	langer then necessary. We need a good reason to include a
	new feature. ``I think it is nifty'' isn't a reason.
	Experience shows that whatever you suggest someone will
	find a way of doing almost the same in the language as is
	(in case of operator.() use the pointer model instead of
	the reference model and overload operator->() and/or
	operator*() instead) so be sure to argue why you shouldn't
	just program around the problem.

(3) Does it fit with the rest of the language?
	This is the point that the operator.() discussion addressed.

(4) Any experience?
	Has anyone implemented this? Used this? Is there experience
	with something like this in other languages? In C++?
	(Note that the `no experience' argument was levelled against
	the template proposal - and rightly so, the issue MUST be
	raised for every suggested extension - and only laid to
	rest when we counted out half a millon lines of existing
	production code implemented using several independent early
	implementations. People had not been idle during the two
	years since my original template proposal. Even then a few
	people found the evidence of experience only barely
	satisfactory).

(5) What is the impact on the rest of the language?
	Language complexity? Consequential changes? Compiler complexity?
	Compile time overheads? Run time overheads? Easy to teach?
	Will it break any existing code? Will its implementation force
	recompilation of existing code?
	(For operator.() I'd rate such impact minimal).

(6) Are there
	(a) alternative ways of providing a feature to serve the need?
	(b) alternative ways of using the syntax suggested?
	(c) attractive generalizations of the suggested scheme 
	For operator.() this could be an issue since several
	alternative suggestions have been made. For example,
	Andrew Koenig suggested a way of treating operator.()
	as a binary operator. I quote:

	``	class Foo {
		private:
			int realsize;
		public:
			int& operator.size() {
				/* do something with `realsize' if needed */
				return realsize;
			}
			// ...
		};

		Then, if foo is a Foo:

		Foo  foo;

		any access to foo.size (without parentheses) would become
		a call to foo.operator.size().''

	Is this an alternative or a complementaty feature? What are the
	ramifications?

Remember that the purpose of the committee is to standardize not
to (re)invent the language. If you want something done, make it easy
for them/us. Do as much of their work for them/us. They/we have only
a limited amount of time and energy and a LOT of work to do to fulfill
their/our charter. You would not like a ``thank you for sharing'' form
letter in response to your suggestion and they/we would not like to
have to send one.

	- Bjarne

aardvark@cooper.cooper.EDU (Rob Horn ) (09/28/90)

in article <11388@alice.UUCP>, bs@alice.UUCP (Bjarne Stroustrup) says:
> 
> (5) What is the impact on the rest of the language?
> 	Language complexity? Consequential changes? Compiler complexity?
> 	Compile time overheads? Run time overheads? Easy to teach?
> 	Will it break any existing code? Will its implementation force
> 	recompilation of existing code?
> 	(For operator.() I'd rate such impact minimal).

What about the case where someone decides to:

	int operator.(int i, int j) {
		return i*j;
		}
			.
			.
			.

	cout << 12.34 << "\n";

Will the compiler see 12.34 as a floating point number, or
as (int) 12 . (int) 34 ?

Just a thought.