www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to copy const object?

reply Mitacha <mateusz.mitaszka gmail.com> writes:
I've a const struct object and I'd like to make a mutable copy of 
it.
Struct definition contains string and an array of structs.
```
struct A {
     string a;
     B[] b;
}

struct B {
     string a;
     string b;
}
```
As far as I can tell copy constructor isn't generated for struct 
`A` because it contains an array. Correct?

Is there an idiomatic way to create copy of a const object?
Feb 27 2020
parent Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Thursday, 27 February 2020 at 11:28:11 UTC, Mitacha wrote:
 I've a const struct object and I'd like to make a mutable copy 
 of it.
 Struct definition contains string and an array of structs.
 ```
 struct A {
     string a;
     B[] b;
 }

 struct B {
     string a;
     string b;
 }
 ```
 As far as I can tell copy constructor isn't generated for 
 struct `A` because it contains an array. Correct?

 Is there an idiomatic way to create copy of a const object?
As long as the copy is also const, you can just assign it to a new variable of the same type: const A a = A("foo",[B("bar", "baz")]); const A b = a; If, however, you require a mutable copy, things get a little more hair. In D, const is transitive, so that A.b[0] is a const(B). This will thus not work: A c = a; // Error: cannot implicitly convert expression a of type const(A) to A For built-in arrays, the .dup function does this: const int[] arr1 = [1]; int[] arr2 = arr1; // Fails to compile int[] arr3 = arr1.dup; // Works For symmetry, we can add a similar function to A: struct A { string a; B[] b; A dup() const { return A(a, b.dup); } } This lets us easily create a copy: A d = a.dup; Now, the reason you can't just assign from const(A) to A, while this works with const(B) to B, e.g., is that A contains mutable indirections. That is, you can change the contents of A.b. Since copies are generally shallow copies in D, allowing this behavior would have unfortunate consequences: const(A) a1 = A("foo", [B("bar", "baz")]); A a2 = a1; // Assume this worked assert(a1.b[0].a == "bar"); a1.b[0].a = "qux"; // Can't change b[0] through a1, since it's const a2.b[0].a = "qux"; // But we can change it through a2! assert(a1.b[0].a != "bar"); // And suddenly the const value in a1.b has changed. -- Simen
Feb 27 2020