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