digitalmars.D - Easteregg: riddle of opIndex<op>Assign solved (nearly)
- Manfred Nowak (92/92) Feb 13 2007 The solution uses chaining.
The solution uses chaining. Let me show how to implement a class C that mimics a dynamic array, like "int[10] data" with _all_ possible "opIndex<op>Assign" overloads. The usage of such a class should look like this void main(){ C a= new C; a[2]= 5; a[2]+= 3 ; writefln( a[2]); // prints 8 } Here I restrict myself to the "opIndexAddAssign". C holds a dynamic array "data". The length of this array is initialized by the constructor. class C{ int[] data; this( ulong len){ data.length= len; } } To start chaining I need a static "opCall" class C{ static C opCall(){ return new C; } } To fetch the lvalue I use "opIndex", which stores the index temporarily: class C{ int index; C opIndex( int inx){ index= inx; return this; } } To fetch the "opIndexAddAssign" I use "opAddAssign", which uses the temporarily stored lvalue index to assign to the correct position in the array: class C{ C opAddAssign(int p){ data[ index]+= p; return this; } } That's it. Drawbacks: 1) The natural rvalue "opIndex" is now used up for an lvalue "opIndex". Therefore a less natural opindex must be defined to return the natural "opIndex": class C{ int opIndex( int inx, int){ return data[inx]; } } A solution to avoid that additional parameter would be to let the compiler emit an "opEOM" on being unable to chain any further, which I have proposed a long time ago: http://www.digitalmars.com/d/archives/26477.html 2) Chaining of assignments is not possible under this scheme. -manfred Full source: import std.stdio; class C{ int[] data; this(int len){ data.length= len; } static C opCall() { return new C(0); } int index; C opIndex( int inx){ index= inx; return this; } int opIndex( int inx, int){ return data[inx]; } C opAddAssign(int p){ data[ index]+= p; return this; } void opIndexAssign(int p, int x){ data[ x]= p; } } void main(){ C a= new C(10); a[2]= 5; a[2]+= 3 ; writefln( a[2 ,0]); // an ugly point }
Feb 13 2007