On Mon, 27 May 2013 14:08:12 +0200, Joseph Rushton Wakeling <joseph.wakel...@webdrake.net> wrote:

On 05/26/2013 05:59 PM, Ali Çehreli wrote:
On 05/26/2013 05:38 AM, Simen Kjaeraas wrote:


     Tuple!(size_t, size_t)[][] data = createData();
     immutable dataImm = assumeUnique(data);
     data = null; // Simply to ensure no mutable references exist.

The last line is not needed. assumeUnique already does that. :)

That's fantastic, thank you both very much. Does that also work for arbitrary data structures (e.g. also associative arrays, complex structs/classes etc.)?

Absolutely. So long as your code does not squirrel away other, mutable
references to the data, assumeUnique is perfectly safe.


Related question -- assume that I now want to store that immutable data inside a
broader storage class, but I want that storage class to be agnostic as to
whether the data is immutable, const or mutable.

Something like this:

        class MyDataStore
        {
                float[] someData;
                uint[] someMoreData;
                Tuple!(size_t, size_t)[][] importedData;

                this(float[] sd, uint[] smd, Tuple!(size_t, size_t)[][] id)
                {
                        someData = sd;
                        someMoreData = smd;
                        importedData = id;
                }
        }

... which of course fails if you try passing it immutable data for any of the
parameters.  So, is there a way to make this broader storage class
type-qualifier-agnostic?

I guess applying "inout" to the input parameters is necessary, but it's clearly
not sufficient as the code then fails when trying to assign to the class'
internal variables.

A few questions:

Why use a class? Will MyDataStore be subclassed?

Will you have some instances of MyDataStore that will be mutated, and
others that will always stay the same?

If the answer was yes, will these be in the same array?


Short answer: If you will have mixed arrays, no. There's no way to make
that safe. If you don't have mixed arrays, there are ways.

This will work:

import std.stdio : writeln;
import std.exception : assumeUnique;
import std.typecons : Tuple, tuple;

class MyDataStore
{
    float[] someData;
    uint[] someMoreData;
    Tuple!(size_t, size_t)[][] importedData;

inout this(inout float[] sd, inout uint[] smd, inout Tuple!(size_t, size_t)[][] id)
    {
        someData = sd;
        someMoreData = smd;
        importedData = id;
    }
}

void main( ) {
    float[] sdMut = [1,2,3];
    uint[] smdMut = [4,5,6];
Tuple!(size_t, size_t)[][] idMut = [[tuple(0u, 0u), tuple(0u, 1u)],[tuple(1u, 0u), tuple(1u, 1u)]];
    immutable float[] sdImm = [1,2,3];
    immutable uint[] smdImm = [4,5,6];
immutable Tuple!(size_t, size_t)[][] idImm = [[tuple(0u, 0u), tuple(0u, 1u)],[tuple(1u, 0u), tuple(1u, 1u)]];

    auto a = new MyDataStore(sdMut, smdMut, idMut);
    immutable b = new immutable MyDataStore(sdImm, smdImm, idImm);
    const c = new const MyDataStore(sdImm, smdMut, idImm);
}

(Tested with 2.063 beta, it's possible there are complications in 2.062)

--
Simen

Reply via email to