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.