How to copy const object?

Simen Kjærås simen.kjaras at gmail.com
Thu Feb 27 12:41:01 UTC 2020


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




More information about the Digitalmars-d-learn mailing list