Duplicating multidimensional array

Joseph Rushton Wakeling joseph.wakeling at webdrake.net
Wed May 29 10:22:44 PDT 2013


Hello all,

I've been having some trouble trying to work out how to effectively duplicate a
multidimensional array in a way that preserves type qualifiers.

Now, obviously if we have a multidimensional array such as T[][] then calling
.dup will duplicate only the base array; so if we do something like,

      int[][] x = [[10, 0, 0, 0], [0, 10, 0, 0], [0, 0, 10, 0], [0, 0, 0, 10]];
      int[][] y = x.dup;

then y[i][j] will still be pointing to the same memory location as x[i][j].

We can write a "multidimensional duplication" function like this:

      T[][] multidup(T)(T[][] x)
      {
            T[][] tmp;
            foreach(row; x) {
                  tmp ~= row.dup;
            }
            return tmp;
      }

... which works for mutable T, but fails with const or immutable.

I had a go at implementing a version for const/immutable use:

      inout(T)[][] multidup(T)(T[][] x) inout
            if(!isMutable!T)
      {
            Unqual!T[][] tmp;
            foreach(row; x) {
                  tmp ~= row.dup;
            }
            return assumeUnique(tmp);
      }

... but this actually doesn't work for const (as assumeUnique only works with
immutable) and even with immutable input falls over:

dupmatrix.d(20): Error: cannot implicitly convert expression (assumeUnique(tmp))
of type immutable(int[])[] to const(int)[][]
dupmatrix.d(26): Error: template instance dupmatrix.multidup!(const(int)) error
instantiating
dupmatrix.d(26): Error: multidup (const(int)[][] x) is not callable using
argument types (const(int[][]))
/opt/ldc/include/d/std/range.d(611): Error: static assert  "Cannot put a char[]
into a Appender!(string)"
    instantiatied in /opt/ldc/include/d/std/format.d(1439):
put!(Appender!(string), char[])
    instantiatied in /opt/ldc/include/d/std/format.d(1341):
formatUnsigned!(Appender!(string), char)
    instantiatied in /opt/ldc/include/d/std/format.d(1315):
formatIntegral!(Appender!(string), ulong, char)
    ... (12 instantiations, -v to show) ...
    instantiatied in /opt/ldc/include/d/std/stdio.d(822):
formattedWrite!(LockingTextWriter, char, const(int[])[])
    instantiatied in /opt/ldc/include/d/std/stdio.d(1707):
write!(string,const(int[])[],char)
    instantiatied in dupmatrix.d(28): writeln!(string,const(int[])[])
joseph at wakeling:~/code/test/D$ vi dupmatrix.d
joseph at wakeling:~/code/test/D$ ldmd2 dupmatrix.d
dupmatrix.d(20): Error: cannot implicitly convert expression (assumeUnique(tmp))
of type immutable(int[])[] to immutable(int)[][]
dupmatrix.d(26): Error: template instance dupmatrix.multidup!(immutable(int))
error instantiating
dupmatrix.d(26): Error: multidup (immutable(int)[][] x) is not callable using
argument types (immutable(int[][]))
/opt/ldc/include/d/std/range.d(611): Error: static assert  "Cannot put a char[]
into a Appender!(string)"
    instantiatied in /opt/ldc/include/d/std/format.d(1439):
put!(Appender!(string), char[])
    instantiatied in /opt/ldc/include/d/std/format.d(1341):
formatUnsigned!(Appender!(string), char)
    instantiatied in /opt/ldc/include/d/std/format.d(1315):
formatIntegral!(Appender!(string), ulong, char)
    ... (12 instantiations, -v to show) ...
    instantiatied in /opt/ldc/include/d/std/stdio.d(822):
formattedWrite!(LockingTextWriter, char, immutable(int[])[])
    instantiatied in /opt/ldc/include/d/std/stdio.d(1707):
write!(string,immutable(int[])[],char)
    instantiatied in dupmatrix.d(28): writeln!(string,immutable(int[])[])

... at which point I feel that I really don't understand the type (and type
conversion) system well enough to proceed without advice :-(

Complete code attached.  Ideally I'd really like to have a solution that would
recursively extend to multidimensional arrays of _any_ dimension, just because I
guess that would be generally useful to everyone.

It strikes me that as the copy is scoped, I might be able to just do a cast from
Unqual!T[][] to T[][] safely, but it doesn't feel good to do so.

I remember Dan Davidson had some code for a "generic dup" function for structs
[1] that might be relevant here (and might already provide a general solution
for multidimensional arrays), but I thought I'd ask if anyone else has any ideas.

[1]
http://www.digitalmars.com/d/archives/digitalmars/D/proposal_for_general_dup_function_182985.html
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dupmatrix.d
Type: text/x-dsrc
Size: 537 bytes
Desc: not available
URL: <http://lists.puremagic.com/pipermail/digitalmars-d-learn/attachments/20130529/43ceb150/attachment.d>


More information about the Digitalmars-d-learn mailing list