On 20/07/12 17:12, Andrej Mitrovic wrote:
According to TDPL postfix operators are rewritten to call prefix
operators, e.g. on this call for some user-type object named a:
auto b = a++;
// is converted to:
auto b = ((ref x) { auto t = x; ++x; return t; })(a);
But I don't see how this is reasonable for classes. Examine:
struct Struct {
int x = 1;
Struct opUnary(string op : "++")() {
x++;
return this;
}
}
class Class {
int x = 1;
Class opUnary(string op : "++")() {
x++;
return this;
}
}
void main()
{
Struct foo1;
Struct foo2 = foo1++;
assert(foo1.x != foo2.x); // ok
Class bar1 = new Class;
Class bar2 = bar1++;
assert(bar1.x != bar2.x); // fail
}
It's clear why, the rewrite that calls "auto t = x" simply binds
another reference to the same object.
Unfortunately this makes it hard to wrap C++ libraries which have both
prefix/postfix operators defined. Currently I wrap these in e.g.
"preInc"/"postInc" methods and I explicitly disable the prefix/postfix
opUnary methods.
Are the semantics of this rewrite ok with people who use op overloads?
I found them to be surprising, but then again I don't use op overloads
that much, I'm just noticing the difference between C++ and D.
But classes have reference semantics, so they are already completely
different from C++.
The question really is, do postfix ++ and -- make sense for reference
types? Arguably not. From a theoretical sense, the existing behaviour
does make sense, but in practice, every time it is used, it is probably
a bug.
The only other reasonable option I can think of would be to make class++
be of type void, so that you could still write
bar1++;
but not bar2 = bar1++;
since the existing behaviour can be achieved by writing bar2 = ++ bar1;