On Thursday, 3 January 2013 at 07:03:23 UTC, monarch_dodra wrote:
On Thursday, 3 January 2013 at 00:08:12 UTC, Peter Summerland
wrote:
On Wednesday, 2 January 2013 at 03:52:21 UTC, bearophile wrote:
Era Scarecrow:
Well I see that you have opIndexUnary twice; According to
the manual you wouldn't need as it would rewrite the code so
you only need it once;
And as you have seen if you remove the useles opIndexRight
the program keeps compiling with no errors and keeps
asserting at run-time:
struct Foo {
int x;
alias this = x;
}
class Bar {
Foo[] data;
this() {
data.length = 10;
}
Foo opIndex(uint i) {
return data[i];
}
void opIndexUnary(string op)(uint i) if (op == "++") {
data[i]++;
}
}
void main() {
auto barfoo = new Bar;
++barfoo[3];
assert(barfoo.data[3] == 1);
barfoo[3]++;
assert(barfoo.data[3] == 2);
}
Bye,
bearophile
I am really just guessing, but it appears that whatever the
post increment op gets rewritten as takes either a reference
to or a copy of what is being incremented and it involves
opIndex, not opIndexUnary as suggested by TDPL p. 378 and p.
369.
Thanks for responding.
On rereading, maybe TDPL is just suggesting that the rewrite for
a[i]++ should be handled exactly the same as foo++, where foo and
a[i] are Foos. I.e., if the result of a[i]++ is not used, rewrite
it as ++a[i]. That apparently is not happening, as reported in
bug 5044. But if a[i]++ is used, then apply
(ref x){auto t=x; ++x; return t;} to (a[i])
which causes the function to be applied to a copy of a[i],
resulting in the nop effect of a[i]++ (unless a[i] returns a ref,
and we don't want that). So IMHO using the the general rewrite at
p369 for indexed items is incorrect. And base don my probing, I
am guessing that the general rewrite is indeed applied to a[i]++.
Would it be possible to have the compiler call
opIndexUnary!"<op>"(b1, ...bk) where <op> could be, say, "post++"
and "post--" in addition to "++" and "--", when appropriate?
Seems like a simple solution.
That's a (old) bug. If opIndexUnary is present, then that
should be called. However, currently, the compiler doesn't
"see" it when it sees "a[i]++".
http://d.puremagic.com/issues/show_bug.cgi?id=5044
"++a[i]" works correctly (AFAIK). If you want to test opUnary,
DO NOT toy around with the post increment index version. Just
stick to simple unary:
"++a" and "a++"
Sorry for the messy example, but I did not mean to test opUnary.
In the code, I just wanted to see if the rewrite of a[i]++ was
calling it (which it is - in version A and version B).
If opIndex is changed to return ref Foo, everything works. (I
had change alias this = x to alias x this - 2.60 64 bit). Here
is code that shows when opIndexUnary and opIndex is called and
when the assertion fails for version(B) - with ref and
version(A) without ref.
As soon as opIndex returns a ref, then *nothing* of
opIndexSomething becomes necessary (heck, it becomes "counter
necessary"). Same thing for front. If front returns by ref,
then you don't need the "front(T t)" variant.
I don't have TDPL under my eyes right now, but I remember it
explicitly stating that these functions where specifically
meant to emulate access primitives, for functions that can't
ref access to its primitives. In particular, for things like
array bool.