James Kanze wrote:
> On Jun 7, 9:53 am, Tomás Ó hÉilidhe <t...@lavabit.com> wrote:
>> Operator overloads are just like any other member function,
>> you can make them do whatever you want. However, of course, we
>> might expect them to behave in a certain way. The ++ operator
>> should perform some sort of increment, the / operator should
>> do something along the lines of division.
>
> And of course, + and * are commutative, where as - and / aren't.
That would rule out many reasonable uses of * like matrix multiplication,
multiplication in other groups, or the use of + for string concatenation.
>> Do you think it would have been worthwhile for the C++
>> Standard to "codify" this expected use of operator overloads?
>
> I think this was rejected in the early days of C++. I'm not
> sure I agree with this, but it's far too late to change it now.
> It's even violated regularly in the standard: think of operator+
> on strings, for example, and there are examples in mathematics
> where operator* wouldn't be commutative either.
Exactly. I would really deplore a language that allows operator overloading
but does not acknowledge the possibility of non-commutative multiplication.
I guess, it all comes down to your attitude toward operator overloading in
general. I see two main possible operator coding styles: (a) have your
operators mimmick the built-in versions so that a person with C++ knowledge
will understand the code easily, or (b) try to make client code look
similar to formula from text books about the problem domain so that a
persion with background knowledge can understand the code easily. I usually
follow (b) and in that case, * is clearly to be used for matrix
multiplication (since we cannot overload whitespace

. But I do see that
those coding guidelines should be local and do not generalize from one
place to another. Therefore, I think the standard made the right decision
not to legislate style.
> The rejection was complete; I think it arguable that there are
> two difference cases: one concerning such "external" rules, and
> another concerning internal rules, e.g. the relationship between
> + and +=, for example, or prefix and postfix ++.
>
>> I'll be specific:
>
>> Let's say you overload the ++ operator, both the pre and the
>> post form. In our class, they both behave as expected: The pre
>> gives you the new value, the post gives you the old value. In
>> our particular implementation, the pre version is much more
>> efficient that the post version because the post version
>> involves the creation of a temporary (and let's say our class
>> object is quite expensive to construct).
>
>> Let's say we have code such as the following:
>
>> for (OurClass obj = 0; obj < 77; obj++) DoSomething;
>
>> When the compiler looks at this, it can see straight away that
>> the result of the incrementation is discarded. If it has some
>> sort of "codified expected usage" of operator overloads, it
>> could invoke "++obj" instead.
>
> If the functions involved are all inline, it can skip the
> construction of the extra object anyway. And if they aren't,
> and can't reasonably be made inline, then it is probable that
> skipping the copy won't make a measurable difference anyway.
> (It's easy to invent perverse cases where it would, but they
> don't occur in real code.)
>
> The important difference would be applying the rules of
> associativity, commutivity, and why not, distributivity (should
> the compiler also assume that addition is cheaper than
> multiplication).
Such rules cannot be applied by the compiler even for signed intergral types
as intermediate results could differ, which in case of overflows might turn
defined behavior into undefined behavior (if you are on a platform where
signed overflow really causes trouble, that is). Similarly for floating
point arithmetic, some path might yield nan whereas a mathematically
equivalent expression might yield 1.0.
For better or worse, arithmetic on computers simply does not obey the usual
mathematical laws; and pretending it does is a surefire method to get into
trouble.
[snip]
Best
Kai-Uwe Bux