Deep dupping

Philippe Sigaud philippe.sigaud at gmail.com
Sun Mar 21 06:33:20 PDT 2010


Hi,

in the "confused about const" thread, some said that we'd need a deep dup, to recursively dup all members of aggregates. I indeed have such a need, so I tried to code a quick & dirty version of this, any comment is welcome:

----
template TypeofDeepdup(T)
{
    alias typeof(deepdup(T.init)) TypeofDeepdup;
}

ref Unqual!T deepdup(T)(T t) if (is(T == struct) && !is(T.Types))
{
    staticMap!(TypeofDeepdup, typeof(t.tupleof)) tup;
    foreach(i,Type; tup) { tup[i] = deepdup(t.tupleof[i]);}
    return Unqual!T(tup);
}

Tuple!(staticMap!(TypeofDeepdup, T.Types))
deepdup(T)(T t) if (is(T.Types)) // Tuples
{
    staticMap!(TypeofDeepdup, T.Types) tup;
    foreach(i,Type; tup) { tup[i] = deepdup(t.field[i]);}
    return tuple(tup);
}

Unqual!T deepdup(T)(T t) if (is(T == class))
{
    staticMap!(TypeofDeepdup, typeof(t.tupleof)) tup;
    foreach(i,Type; tup) { tup[i] = deepdup(t.tupleof[i]);}
    return new Unqual!T(tup);
}

TypeofDeepdup!(ElementType!T)[] deepdup(T)(T t) if (isDynamicArray!T)
{
    auto result = new TypeofDeepdup!(ElementType!T)[](t.length);
    foreach(elem; t) result ~= deepdup(elem);
    return result;
}

TypeofDeepdup!(ElementType!T)[T.length] deepdup(T)(T t) if (isStaticArray!T)
{
    TypeofDeepdup!(ElementType!T)[T.length] result = t;
    foreach(ref elem; result) elem = deepdup(elem);
    return result;
}

TypeofDeepdup!T* deepdup(T)(T* t)
{
    return &deepdup(*t);
}

Unqual!T deepdup(T)(T t) if (!is(T == struct) && !is(T == class) && !isDynamicArray!T && !is(T.Types) && !isPointer!T)
{
    return cast(Unqual!T)t;
}
----

I have to unqualify everything, getting rid of const and immutable, to be able to copy what I want. My current problem are strings, for somehow ElementType!(StringType) returns dchar. I'll probably have to special-case them, and use std.string.ByCodeUnit.


It seems to work well enough for my needs : structs, pointers to structs, classes, dynamic and static arrays, all recursively.
One big limit for now: templated structs/class whose type depend on their internal types. Eg: Tuples.

Tuple!(string, int) should become Tuple!(dchar[], int). That's more or less the current situation for structs, by I found no way to do this generically for all templates.


Another limit is that everything is returned unqualified...
Also, I'll wait for auto ref and inout to stabilize before using them in deepdup.

Any comments/ideas?

  Philippe


More information about the Digitalmars-d-learn mailing list