Search code examples
d

How to duplicate of a const slice of structs in D?


Let's assume I have a struct, that contains a slice:

struct Test{
    int[] arr; 
}

The problem is, that I'm unable to duplicate a const version of the Test struct:

void function(in Test tmp){
    ....
    Test copy = tmp.dup;//Compilation failure
    ....
}

I understand that the compile time error comes from the fact that copy and tmp would share the same arr slice, that would brake tmp constness. How to avoid this problem, without taking a non const Test object?


Solution

  • Easiest fix is to explicitly make a copy of Test with a copy of tmp:

    Test copy = Test(tmp.arr.dup); // works
    

    Here's a more generic duplicate function and example program:

    struct Test{
        int[] arr; 
    }
    
    void f(in Test tmp) {
        Test copy = tmp.duplicate;
        import std.stdio;
        writeln(copy);
        copy.arr[0] = 10;
        writeln(copy);
        writeln(tmp);
    }
    
    import std.traits;
    
    T duplicate(T)(in T t) if(is(T == struct)) {
        T copy;
        foreach(memberName; __traits(allMembers, T)) {
            static if(!hasIndirections!(typeof(__traits(getMember, t, memberName))))
                __traits(getMember, copy, memberName) = __traits(getMember, t, memberName);
            else
                __traits(getMember, copy, memberName) = __traits(getMember, t, memberName).dup;
        }
        return copy;
    }
    
    void main() {
        auto t = Test([20, 30]);
        f(t);
    }
    

    It loops over all members of the input struct and if it is a value type, just assigns it to a copy, and if not, tries to call .dup on it to make a copy. Works with array members. With some expansion, you could make it work with child structs and maybe pointers too.