A opIndexUnary quiz

monarch_dodra monarchdodra at gmail.com
Wed Jan 2 23:03:18 PST 2013


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.

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++"

> 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