What is special about an immutable array of class objects, and why can I not .dup ?

Jonathan M Davis newsgroup.d at jmdavisprog.com
Mon May 28 14:02:28 UTC 2018


On Monday, May 28, 2018 13:51:49 James Blachly via Digitalmars-d-learn 
wrote:
> Consider the below:
>
> ```
> class C
> {
>      int x;
> }
>
> struct S
> {
>      int x;
> }
>
>
> void main()
> {
>   immutable C[] c = [ new C(), new C()];
>   immutable S[] s = [ S(), S() ];
>      immutable int[] i = [ 1, 2 ];
>
>      auto x = c.dup;
>      auto y = s.dup;
>      auto z = i.dup;
>
> }
> ```
>
> This fails to compile with a `.dup` template matching error at
> line `auto x = c.dup;`. However, calling `.idup` works just fine.
> The immutable struct array and int array of course `.dup` just
> fine.
>
> I would have guessed that changing the definition of `C[]` to
> `immutable(C)[]` would have also helped, but it did not.
>
> Why are the class objects special in this case, and why does
> `immutable(C)[]` not help?   I believed that this defined a
> dynamic array `c` which was itself mutable, the elements of which
> were immutable.
>
> Thanks for insights.

dup makes the entire thing mutable, and the compiler can't safely convert
immutable class references to mutable ones. And when you think about it, the
immutability of the array itself really isn't the key thing here anyway. All
you have to do to get a mutable one is to slice it - slicing gives you a
tail-const/tail-immutable dynamic array pointing to the same data. So,
ultimately, what you're doing with dup vs idup is deciding what the
mutability of the elements is. dup makes them mutable, and idup makes them
immutable. In the case of primitive types or structs which don't have
postblit constructors, that's usually trivial, but it doesn't work with
class references. For them, you're stuck with the same level of mutablity,
because there is no easy conversion for them between mutable and immmutable.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list