Fixed size multidimensional array at runtime
Artur Skawina
art.08.09 at gmail.com
Sun Jul 1 06:30:54 PDT 2012
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]);
}
More information about the Digitalmars-d-learn
mailing list