On 06/30/12 22:06, Vidar Wahlberg wrote: > Although it seems to me that you still end up with "matrix[x, y, z]" instead > of "matrix[x][y][z]", so it will only solve one half of the problem :) > For this particular case I'll just do the conversion from two-dimensional to > one-dimensional array programmatically and use a "get(x, y)"-method,
"matrix[x,y,z]" is a problem, yet "matrix.get(x,y,z)" is fine? Anyway, converting one syntax to the other is trivial - see example below. You also get the "matrix[x,y][z]" and "matrix[x][y,z]" syntax as a bonus. All of the neatIdx glue gets optimized away, so in this case there's zero extra overhead - but this is not something I'd count on in general. It actually surprised me how well gcc manages to handle it; even in the variable-indexes case the compiler only emits a few adds and shifts. artur import std.stdio; template IDS(A...) { alias A IDS; } static struct NeatIndex(A, uint N=0) { import std.traits; A* a; ParameterTypeTuple!(A.opIndex)[0..$-1] idxs; auto ref opIndex(IDXS...)(IDXS args) if (N+args.length==idxs.length+1) { return (*a)[idxs[0..$-args.length+1], args]; } auto ref opIndex(IDXS...)(IDXS args) if (N+args.length<idxs.length+1) { idxs[N..N+args.length] = args; return *cast(NeatIndex!(A, N+args.length)*)&this; } } NeatIndex!A neatIdx(A)(ref A a) { NeatIndex!A na = {&a}; return na; } void main() { static struct A { int[3][3][3] data; auto ref opIndex(size_t x, size_t y, size_t z) { return data[x][y][z]; } } A a; foreach (z; 0..3) foreach(y; 0..3) foreach(x; 0..3) a[z,y,x] = 100*z+10*y+x; static assert(!__traits(compiles, a[2][1][0])); auto b = neatIdx(a); writeln(b[2,1,0]); writeln(b[2,1][0]); writeln(b[2][1,0]); writeln(b[2][1][0]); writeln(neatIdx(a)[2][1][0]); }