Simple immutable example doesn't work - why???

Kenji Hara k.hara.pg at gmail.com
Tue Nov 12 00:06:43 PST 2013


On Tuesday, 12 November 2013 at 01:15:02 UTC, Louis Berube wrote:
> Thanks, I think I understand. Now, how about an array of 
> immutables:
>
> immutable class Test
> {
>     public:
>         this(in uint value)
>         {
>             this.value = value;
>         }
>         unittest
>         {
>             auto t = new immutable Test(4);
>             assert (t.value == 4);
>         }
>         unittest
>         {
>             auto tarray = new immutable(Test)[3];
>             tarray[0] = new immutable Test(4);
>                                     // "Error: cannot modify
>                                     // immutable expression
>                                     // tarray[0]"
>         }
>     private:
>         uint value;
> }
>
> I thought the parantheses in the array declaration would do the 
> trick, but apparently not.

Once you initialize an immutable class reference, you won't be 
able to rebind it anymore.
As far as I know there's two straight methods.

immutable class Test
{
     this(in uint value)
     {
         this.value = value;
     }
     uint value;
}

void main()
{
     version(Try1)
     {
         // 1. concatenate elements
         immutable(Test)[] tarray;
         tarray ~= new immutable Test(2);
         tarray = new immutable Test(1) ~ tarray;
     }
     else
     {
         // 2. use array literal syntax
         auto tarray = [
             new immutable Test(1),
             new immutable Test(2),
         ];
     }
     static assert(is(typeof(tarray[0]) == immutable(Test)));
     assert(tarray.length == 2)
     assert(tarray[0].value == 1);
     assert(tarray[1].value == 2);
}

In D, you can reserve continuous memory area for array appending 
by using built-in 'reserve' method. Therefore in most cases, 
"reserve elements on empty array, then append created elements" 
would be the efficient way to initialize the array of immutable 
elements.

void main()
{
     immutable(Test)[] tarray;

     tarray.reserve(2);
     auto save_ptr = tarray.ptr;
     assert(save_ptr !is null && tarray.capacity >= 2);
     // underlying memory is allocated and the appendable number 
is more than 2.

     assert(tarray.length == 0);
     // but array itself is still empty.

     tarray ~= new immutable Test(1);
     tarray ~= new immutable Test(2);

     assert(tarray.length == 2);
     // array is expectedly filled.

     assert(tarray.ptr is save_ptr);
     // But the two concatenations didn't reallocate underlying 
memory.
}

And I don't recommend to use std.exception.assumeUnique, because 
it is just a cosmetic function to make ugly (but necessary for 
some reason) array cast grep-able and human-readable.

Kenji Hara


More information about the Digitalmars-d-learn mailing list