On Thursday, 15 March 2018 at 15:41:54 UTC, Robert-D wrote:
Why something like this doesn't compile (with or without the cast on bb.dup)?

struct S {
    string[string] aa;

    S dup() inout pure {
        return S(cast(string[string]) aa.dup);
    }
}

struct SS {
    S[] bb;

    SS dup() inout pure {
        return SS(cast(S[]) bb.dup);
    }
}

Or:

const(S)[] ss = [S(["": ""])];
S[] d = ss.dup;

For this to work, the standard .dup function would need to call .dup on each element of the array. Since this may or may not be what the programmer wants, the standard library doesn't do it for you. Generally, this is called deep-duping, or deep cloning. We can implement our own deepdup function:

struct S {
    string[string] aa;

    S dup() const {
        return S(aa.deepDup);
    }
}

struct SS {
    S[] bb;

    SS dup() const {
        return SS(cast(S[])bb.deepDup);
    }
}

import std.traits : Unqual, isArray, isAssociativeArray;

auto deepDup(T)(T obj)
if (!isArray!T && !isAssociativeArray!T)
{
    static if (is(typeof(obj.deepDup))) {
        return obj.deepDup;
    } else static if (is(typeof(obj.dup))) {
        return obj.dup;
    } else static if (is(typeof({ Unqual!T tmp = obj; }))) {
        return obj;
    } else {
        static assert(false, "Can't deepDup a "~T.stringof);
    }
}

auto deepDup(T)(T[] arr) {
    Unqual!T[] result;
    result.reserve(arr.length);

    foreach (e; arr) {
        result ~= e.deepDup;
    }

    return result;
}

auto deepDup(T : V[K], K, V)(T aa) {
    alias UV = Unqual!V;
    alias UK = Unqual!K;
    UV[UK] result;

    foreach (k, v; aa) {
        UK kdup = k.deepDup;
        UV vdup = v.deepDup;

        result[kdup] = vdup;
    }

    return result;
}

--
  Simen

Reply via email to