A opIndexUnary quiz
Peter Summerland
p.summerland at gmail.com
Thu Jan 3 10:08:51 PST 2013
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.
More information about the Digitalmars-d-learn
mailing list