Path: utzoo!mnetor!uunet!husc6!bloom-beacon!gatech!rutgers!mtune!mtunx!whuts!mhuxh!mhuxt!mhuxu!mhuxi!mhuhk!mhuxo!ulysses!andante!alice!bs From: bs@alice.UUCP Newsgroups: comp.lang.c++ Subject: Re: C++ enhancements Message-ID: <7757@alice.UUCP> Date: 21 Mar 88 19:16:16 GMT References: <2781@mmintl.UUCP> Organization: AT&T Bell Laboratories, Murray Hill NJ Lines: 150 Summary: we must be very careful franka @ Ashton-Tate Corporation, East Hartford Development Center writes: > Following are some suggestions for improvements to C++. I have nothing in particular against the improvements proposed here, but I will take the opportunity to make a few general points about C++ and its growth. C++ is in widespread use. Much of this use is in non-research environments; there are more than four independent organizations producing C++ compilers and many more building tools and libraries. The implication is that we must be quite restrained when it comes to ``improving'' the language or else we will fracture it into several incompatible dialects. All the compiler writers I know of have expressed a strong support for the idea of ``one language'' and a horror of the specter of ``feature wars'', but only restraint on all parts will make it possible to achieve this. This does not imply that C++ cannot change; it can, will, and does grow. It just means that for the moment we must concentrate on getting the fabric of the language well defined and well documented. Decorating the language with bells and whistles to suit the very diverse tastes of advanced research users could be severely damaging. Compatibility between C and C++ is a major concern. Keeping the language small and clean enough to allow relatively small and relatively clean manuals and compilers is another concern. My contention is that even strictly upwardly compatible changes can become a severe problem if they start appearing so fast that the compiler writers and the users cannot keep up. For example, library writers would forever have to agonize over which extensions they could use without antagonizing ``too many'' of their users. Also consider this: Most of the new features would be irrelevant to YOU as an individual user. You might find that the cost of the ability to write your code in exactly the most elegant way according to your current taste is the ability to run most everybody else's software. And this: Every new feature added choses one evolutinary parth and thereby closes all similar parths. For example, if we provided a built-in set of features for concurrency we would be stuck with it. Even if we found a much better solution tomorrow. This is one of my nightmares. we have many reasons to thread very carefully. > Add a new keyword "leaf" to the language. This is applied to a (virtual) > function declaration to indicate that the function is not redefined in any > subclass of the current class. This enables the translator to generate a > direct call to the function for objects known to be in the current class. I > know that the same thing can be accomplished by prefixing class-name:: to > the call, but I want the facility attached to the declaration, not the call. I think that this is unnecessary: first because a virtual function call is sufficiently efficient compared to a ``normal'' function call to make this optimization far less attractive than in ``other object-oriented programming languages,'' and second because the optimization already can be and is done in many cases. Consider: class B { public: virtual f(); }; class D : public B { public: f(); }; class DD : public D { public: f(); }; f(D a, D* p) { a.f(); // generates a non-virtual call to D::f() // because a is known to be a D. // If D::f() is an inline inlining takes place p->f(); // virtual call: *p might be a DD } > As an extension, one could apply the leaf modifier to a class definition, > which makes it illegal to define an subclasses of the class. This in effect > makes any functions defined for the class leaf functions. This extension would allow p->f() to be handled as a non-virtual by disallowing the definition of DD, but is this optimization important enough to be worth trading away the ability to derive? Is there a real need for disallowing derivation in some cases? (if so, we would no longer be talking about an efficiency hack, but about a feature). > Why not let the result of applying the & operator to a reference variable be > an lvalue? This would mean one could write something like: > int & a = i; > int j; > (&a) = &j; > If the original declaration was "int & const a = i", the assignment would be > illegal. (Note the parentheses around "&a". Permitting them to be dropped > would require a syntax change. This would be better, but I'm not sure off > hand how difficult it would be.) References was carefully designed NOT to be objects. The reason for that is that I disliked every scheme I could think of for treating a reference both a an object in itself an as an ``invisible'' handle for the object it refers to and that given pointers I did not see a reason for doing it. I do not find the solutions provided by Algol68 and Simula attractive - and here I speak from semi-painful experience. In C++, we have both pointers and references. Clearly in an ideal world this is one concept too many and if we eliminated pointers (which we will not do) we would have to provide ways of changing the value of reference objects. However, given that we do have pointers I suggest you use them where the reference semantics are too restrictive. To get back to the example in hand, what don't I like about the scheme outlined above? Assigning to an address (&a) looks a bit funny, but I could get over that. Would &a++ and ++&a be allowed? &a[2] ? (Quick: where do we need parentheses?). Is ``*&a'' always the same as ``a''? Consider: int* p; int*& r = p; &r = p; // currently illegal p = r; p = *&r; // legal? why/why not? *&r = p; // legal? why/why not? *&r = i; // legal? why/why not? p = &*r; // legal? why/why not? *r = 2; // legal? why/why not? **&r = 2; // legal? why/why not? Actually, this proposal is probably the most sensible one I have seen for allowing the value of a reference to change. However, the bottom line is: What do you get by extending the language? In this case I think the answer is (1) a minor notational convenience (2) larger manuals and compilers (3) the need to teach users the answers to my questions above > Has anything been done yet about the ambiguity of prefix and postfix > operators when overloading "++" and "--"? How about "operator postfix ++" > and "operator postfix --", with the unadorned forms being prefix? I am still unconvinced that this extension would add anything significant to C++. I see that it would allow replacing pointers to some basic type with a user-defined pointer type without any program changes (for debugging, etc.) but I'm not convinced this is such a great idea. The distinction between ++i and i++ is subtle and its importance is primarily to save the explicit introduction of a temporary. Is this really the level of improvements we want to see in C++? > It seems like it would be easy to define an alternative form for the "for" > statement: > for { statement expression-opt ; compound-statement } statement > This permits generalized update statements as well as generalized > initialization. (It will mean that "break" statements must, in general, be > translated into "goto"s.) > There has been some discussion recently in comp.lang.c about permitting > aggregate expressions in more general contexts. Has this been considered > for C++? If so, what is its status? Yes, it was considered 6 years ago. My conclusion was and is: use constructors.