From: matt@physics2.berkeley.edu (Matt Austern)
Newsgroups: comp.std.c++,comp.lang.c++
Subject: Re: Exponentiation operator proposal
Date: 14 Sep 92 22:50:05
Organization: Lawrence Berkeley Laboratory (Theoretical Physics Group)
	<BuJJxs.8Hx@world.std.com> <23663@alice.att.com>
Reply-To: matt@physics.berkeley.edu
NNTP-Posting-Host: physics2.berkeley.edu
In-reply-to: bs@alice.att.com's message of 14 Sep 92 14:27:49 GMT


Recently, Bjarne Stroustrup suggested that it would be possible for
the exponentiation operator to be denoted **.  At first sight this
appears to be impossible, since ** already has a very different
meaning in C++, and previous discussions of an exponentiation operator
(mine included) have dismissed this possibility without further
analysis.

This has been excessively hasty.  Exponentiation is only defined if
both operands are of a numeric type; conversely, ** is currently
meaningful only if it precedes a pointer.  There is no overlap, so it
might, therefore, be possible to use type information to disambiguate
these different uses of **.

Specifically, we might consider the following proposal:

--------------------------------------------------------------------

    Two new tokens, ** and **=, will be added to the C++ language.  **
    will be both a unary and a binary operator.  Unary ** will have
    the same precedence as the other unary operators, and binary **
    will have a new precedence level between the multiplicative
    operators and the pointer-to-member operators.

    Unary ** is defined only for an operand which is a pointer to a
    pointer, and it will mean to dereference that operand twice.

    If the arguments to binary ** are both of a numeric type, then it
    denotes exponentiation, and its semantics will be those described
    by my earlier proposal.  If its first operand is of a numeric type
    and its second is a pointer to a number, then it means to multiply
    the first operand by the contents of the second.  For other
    combinations of argument types, binary ** is undefined.

    **= is defined only for the case where the first operand is a 
    modifiable lvalue of a numeric type and the second operand is an
    object of a numeric type; it is defined the same way as the other
    op= operators.

    **=, and unary and binary **, may be overloaded by the user if 
    at least one argument is a class.

---------------------------------------------------------------------- 

This proposal does, at least, implement ** as an exponentiation
operator while continuing to allow its current uses.  However, it
presents several difficulties.

First, it breaks existing code.  To see why it must do so, notice that
in current C++, ** is not a single token; it is a sequence of either a
binary operator followed by a unary operator, or else two unary
operators.  The difficulty is that the binary and the unary operators
have different precedence.  So, in particular, consider the expression
			x/y**p,
which, by the current language definition, is equivalent to
			(x/y) * (*p).
According to the proposal above, however, ** is a single token with a
precedence higher than division, so this expression will mean
			x / (y * (*p)).
I don't know how much code actually contains expressions like this,
but it isn't unreasonable to assume that at least some does.

Second, even in code which won't be broken by this change in the
behavior of **, users will have to examine their code to make sure
that it still means what they thought it did.  ** is a common enough
character sequence (consider, for example, the idiom **argv) that most
programmers will at least have to glance at their code, even if
nothing actually needs to be changed.

Third, the disambiguation rules don't go far enough: they solve the
problem for built-in types, but not for class types.  Users who define
``smart pointers'' will want the dereference operator to work the same
way for their smart pointers as for ordinary C pointers, so, if they
overload unary * to mean smart pointer dereference, they will
similarly be forced to overload unary and binary **.  This imposes an
additional burden on people who use a rather common programming
technique.

** does have one potential advantage over *^ as an exponentiation
operator: that is how exponentiation is denoted in FORTRAN.  I regard
that as a small advantage, however; there is nothing particularly
natural about FORTRAN's use of that symbol, and I believe that
scientific programmers could get used to *^ just as easily as they got
used to the once-unfamiliar **.  In fact, it isn't completely clear to
me that ** would really be more readable as a C++ exponentiation
operator than *^ would be: scientific programmers, like other
programmers, would have to cope with the multiple meanings of **.

I believe that an exponentiation operator would be of genuine benefit
to C++ scientific programmers, and I believe that we who write
scientific code are justified in asking that it be included.  I don't
think, however, that we are justified in asking for a change to the
language that makes life harder for other C++ programmers.  Using **
to denote exponentiation does exactly that: it changes the meaning of
legal C++ code, and it makes a useful programming technique more
difficult.

It is possible to implement an exponentiation operator so that the
extension to the language will have no effect at all for people who
don't deliberately use the new feature.  This is a better idea.





--
Matthew Austern                   Just keep yelling until you attract a
(510) 644-2618                    crowd, then a constituency, a movement, a
austern@lbl.bitnet                faction, an army!  If you don't have any
matt@physics.berkeley.edu         solutions, become a part of the problem!
Newsgroups: comp.std.c++