Duplicating multidimensional array
Ali Çehreli
acehreli at yahoo.com
Thu May 30 00:36:51 PDT 2013
On 05/29/2013 10:22 AM, Joseph Rushton Wakeling wrote:
> I've been having some trouble trying to work out how to effectively
> duplicate a multidimensional array in a way that preserves type
qualifiers.
Templates preserve type qualifiers. So, as long as the return type is
the same as the parameter type, then the type qualifiers should be
preserved:
T foo(T)(T x)
{
// ...
}
> immutable int[][] x = [[10, 0, 0, 0],
> [0, 10, 0, 0],
> [0, 0, 10, 0],
> [0, 0, 0, 10]];
> int[][] y = multidup(x);
As long as it is a conversion, std.conv.to handles that case for you:
import std.conv;
// ...
int[][] y = x.to!(int[][]);
Done! :)
Unfortunately, std.conv.to is not a general copy tool. It does not do
anything when converting to the same type. In other words, when the
target type is the same as the source type it is a no-op, not a copy.
What do you think about the following recursive template solution? I
have tested it only with arrays of int. :/
import std.stdio;
import std.traits;
import std.conv;
// This is for one-dimensional arrays
T multidup(T : E[], E)(T arr)
if (!isArray!E)
{
T result;
static if (is (E == immutable)) {
// No need to copy immutable elements
result = arr;
} else {
// Otherwise, we must make a copy
result = arr.dup;
}
return result;
}
// This is for array of array types
T multidup(T : E[], E)(T arr)
if(isArray!E)
{
T result;
static if (is (E == immutable)) {
// No need to go deeper than an immutable layer
result == arr;
} else {
foreach(row; arr) {
result ~= multidup(row);
}
}
return result;
}
unittest
{
{
int[] a = [ 1, 2, 3 ];
auto b = multidup(a);
assert(typeid(b) is typeid(a));
assert(a == b);
}
{
immutable(int[]) a = [ 1, 2 ];
auto b = multidup(a);
assert(typeid(b) == typeid(immutable(int)[]));
assert(a == b);
assert(a.ptr == b.ptr);
}
{
immutable(int)[] a = [ 1, 2, 3 ];
auto b = multidup(a);
assert(typeid(b) == typeid(a));
assert(a == b);
assert(a.ptr == b.ptr);
// assert(a[0].ptr == b[0].ptr);
}
{
immutable(int)[][] a = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ];
auto b = multidup(a);
assert(typeid(b) == typeid(a));
assert(a == b);
assert(a.ptr != b.ptr);
foreach (i; 0 .. a.length) {
assert(a[i].ptr == b[i].ptr);
}
}
{
alias Elem = const(int[])[];
const(int[])[][]a = [ [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ],
[ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ] ];
auto b = multidup(a);
assert(typeid(b) == typeid(a));
assert(a == b);
assert(a.ptr != b.ptr);
foreach (i; 0 .. a.length) {
assert(a[i].ptr != b[i].ptr);
}
}
}
void main()
{}
Is it usable in your situation?
Ali
More information about the Digitalmars-d-learn
mailing list