Jean Vezina wrote this rebuttal of my assertion that C++ can do
things with operator overloading that Fortran can't:
> And Roger Glover wrote:
>
> >> I admit that C++
> >> has rather more operators than Fortran,
>
> >No doubt about it, that is a definite advantage for C, one that
^[1]
> >I think you are seriously underestimating in your subsequent text.
[1] My mistake. This "C" should be a "C++".
> But these extra operators are artificial, not very intuitive, and have
^^^^^^^^^^[2]^^^^^^^^^^^^^^^^^[3]
> no meaning outside of the C/C++ world.
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^[4]
[2] All almost all operators in any computer language are artificial.
Of the operators commonly used in computer arithmetic, only "+",
"-", "/", "=", "<", and ">" are commonly used outside a computer
context.
Outside computers "x", "."-vertically-centered, and concatenation
are the preferred multiply operators, and although "/" is
sometimes seen for division, "-:" (superimposed), vertical-
separation-by-horizontal-bar, and ")"-with-horizontal-overbar
(long division) are much more common in the non-computer world.
[3] Intuition is based on experience. I, for one, find C's
ampersand (&) to be an utterly intuitive "and" operator, and
asterisk (*), the "footnote reference character," to be an
utterly intuitive "pointer reference" operator.
Other than that, I would have to agree with you, but then again,
most symbolic notation in Fortran is non-intuitive as well.
What is intuitive about "**" for exponentiation? "%" for
structure part selection? ":" and "," for delimiting integer
ranges?
Yes, C and its derivatives have more symbolic notation than
Fortran, but I do not find C's symbols to be in general any
less "intuitive" than Fortran's.
[4] The "C/C++ world" is an extremely big world. The commonly-
used languages that use C operator (and other symbolic) syntax
include Java, JavaScript, awk, lex, yacc, perl, C shell, Bourne
shell, Korn shell, BASH, and Tcl. Even Fortran adopted the
C solution of using "==" for relational equality to avoid
confusion with the assignment symbol "=".
> The precedence rules among them
> are arbitrary and difficult to remember. Look at the number of articles
> published in the C/C++ Users Journal that just explain the way to
> decipher the precedence rules.
I have not seen any that deal with difficulty in the precedence
rules themselves; if you have references I would be glad to look
them over. Most that I have read are about how to use the
precedence rules to decipher declarations. The precedence rules
themselves can be expressed in a simple, easy-to-understand chart.
However, the way some operators are used in C declarations is very
hard to grasp without a clear understanding of *HOW* to apply the
precedence rules to declarations.
Cryptic declaration syntax is a definite Achilles heel for C and
C++, but it has nothing to do with whether Fortran or C++ operator
overloading is "better."
> Overloading operators such as:
>
> += -= ++ -- >> << & && ~
^^^^^^^^^^^[5] ^^[6]
> doesn't lead to code that is easy to understand.
Jean, here you are "talking past me." I said:
> > I have found great value in the ability to overload the syntax for
> > bitwise logic, for pointer reference and dereference, for array
> > element selection, for function calls, for implicit and explicit
> > data type conversion.
Only two of the operators you mention above have anything to do
with any of the categories I mentioned. I realize you are making
your own point (and I will address it later), but your point does
not refute mine. So let me elaborate on my point:
- I have overloaded C++ bitwise logic operators to good
advantage when dealing with simple merging of bitmap images.
The bitwise not operator (~) and the bitwise exclusive or
operator (^) were particularly valuable. If you are a C
programmer who has worked with bitwise logic, you would find
the overloading very natural. If not...
- I have found "reference-counting pointer" templates valuable
for avoiding memory leaks in C++. Key to the implementation
is ability to overload the operators for reference (*) and
dereference (&). Fortran would need a template/generic
facility before I could even begin to think about whether
a hypothetical "assignment( => )" overload could be used
to accomplish the same sort of thing in Fortran.
- About a year ago, my old colleague Dan Nagle posted here
with the need to implement a safe generic interface to a
bit vector data type. At the time he noted that he could
easily have encapsulated his bit vector type if he had used
C++, because he could have overloaded the operators for
array indexing ([]) and assignment (=) to give all the
functionality he needed. There are other cases in which
data is packed in a non-byte-multiple size (some raw weather
data, for example) that can also benefit from the same
approach.
Array indexing can also be overloaded for "database" data
types to give a very elegant, natural "key-indexed" value
retrieval syntax.
- Overloading the C++ function call operator ( () ) can
be used to much the same advantage in "database" types
when there are multiple keys. And there are about half
a dozen other uses for this overloading that are related
to C++ template libraries.
- Implicit data type conversion in C++ has been invaluable
in almost every mathematical data type I have created or
seen, and operator overloading is one of two ways to get
it. I would love to have a syntax for implicit type
conversion in Fortran; I would be able to apply it today
immediately in three different problem areas.
So now lets deal with your point:
[5] About "+= -= ++ --": In a perfect world, "++" should have
its obvious meaning by default whenever "+" is defined for
any integral type, likewise for "--", "-", and any *signed*
integral type; any of the compound assignment operators
should also have its obvious meaning when the primary
operation and "=" are both defined.
Why doesn't it work that way? In early implementations,
separate overloading allowed hand optimization of which the
compilers were not capable. Today's C++ compilers could
have performed such optimizations automatically without
breaking a sweat, but separate definition remains; it's too
late to change it. Of all programmers in the world, Fortran
programmers should understand being stuck with lousy syntax
and limited semantics due to the need to support legacy code.
Nonetheless, the same point could be made about "+" and
"-" in both languages, "*" and "/" in both languages,
".AND." (&&), ".OR." (||), and ".NOT" (!) in both languages,
"==", "/=" (!=), and ".NOT." in both languages, "<" (>),
"==", and "<=" (>=) in both languages. The difference
between C++ and Fortran on this issue is only a matter of
degree.
[6] About "&&": It is a crime against nature that C++ allows
"&&" and "||" to be overloaded without providing some way
of insuring that the key characteristic of "short circuiting"
is preserved, but that represents a capability that Fortran
has never had. I have a hard time scoring this as a point
against C++ when the whole capability is outside the realm of
Fortran.
> The >> and <<
> operators applied to streams have some graphic sense, but their extended
> definition is far from being the left shift and right shift usage
> they have in C.
The mnemonic basis is UNIX shell I/O redirection, not C bit-
shifting (refer to Bjarne Stroustrup, _The Design and Evolution
of C++_, Addison-Wesley, 1994, p. 186).
Since the left and right shift operators are so rarely used in C,
this is not a big learning problem. I have taught C++ to about
two hundred people over the last two and a half years, and not
one has had a problem understanding or using stream I/O operators
by the end of the first morning of class.
That is not to say C++ is easy!! There are *IMMENSE* learning
barriers to be sure, but I/O syntax is not one of them.
------------------------------------------------------------------
After his rebuttal attempt, Jean wrote this reassertion of Clive's
take on the advantage of named operators:
> F90 defined operators have the advantage of being textual, thus self
> explicit.
Function names are also textual, and function calls, generic or
direct, are just as "self explicit." The only advantage I find in
named operators is when "infix" notation is key to understanding.
So, using Clive's examples, I think
USET = UNION( SET1, SET2 ) !! "union of set1 and set2"
could easily replace his ".UNION." operator
USET = SET1 .UNION. SET2 !! "set1 'union' set2"
without loss of comprehension. However,
LFLAG = IN( ELEM(I), SET1 )
could not easily replace his ".IN." operator
LFLAG = ELEM(I) .IN. SET1
since the latter reads much more clearly as if it contained the
preposistional phrase "in set1".
The fact that both of Clive's operators are being used to replace
unavailable infix symbolic math operators does not really make
that much difference; it is the "readability" that counts.
*However*, in C++ one can get the same "infix" effect by using
member functions:
if( elem[i].in( set1 ) ) break
or, more likely:
if( set1.contains( elem[i] ) ) break
which reads just as clearly but does not imply that "elem[i]"
is a "instance of a class."
So, textual operators, while advantageous in some ways, are
not immensely advantageous, and while they provide an infix
effect that C++ cannot match with operator overloading, C++ can
match the effect in other ways.
I still score this contest a 1-1 tie, and I am beginning to feel
more and more that I am being generous to Fortran in doing so.
-------- Cray Research --------- Roger Glover
-- A Silicon Graphics Company -- http://home.cray.com/~glover
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|