I am trying to have a multi-dimensional array and opIndex has to have both an arbitrary number of parameters and allow for slicing.

The problem is if I create opIndex for non-slicing, it looks like

ref auto opIndex(T...)(T index)

and this one catches all templates. But slices do not return the same value. I need to somehow have two opIndex's, one for slice handling and one for non-slices.

Trying to accomplish

arr[1..4, 5..8, 3, 3..4]

I already have the single index case arr[3, 4, 3, 1]

and the only difference is that for a slice, the indices are int[2]'s.

To make this work, I need to somehow know if any of the parameters is a slice or not.

Heres what I've got so far:

struct sMArray(F)
{
        import std.traits, std.meta, core.stdc.stdlib;
        size_t[] dimensions;            // The dimensions of the multi-array
        size_t[] offset;                        // The offset of the 
multi-array(for slices)
        void[] data;                            // An array of the actual 
element data in bytes
void[] parent; // The parent array or slice, if null, no parent.
        
        
this(T...)(T args) // Give the dimensions with one element(first or last) being a flag array to initialize with
    {                   
                static if (isArray!(T[0]))
                {
                        auto dat = T[0];
                        dimensions = args[1..$];
                        enum start = 1;
                        enum end = T.length;

                } else
                {
                        static if (isArray!(T[$-1]))
                        {
                                auto dat = T[$-1];
                                enum start = 0;
                                enum end = T.length-1;
                        } else
                        {
                                int[] dat = null;
                                enum start = 0;
                                enum end = T.length;
                        }                               
                }


                foreach(a; args[start..end])            
                        dimensions ~= a;

                int totalSize = 1;
                foreach(d; dimensions)
                        totalSize *= d;

                data = malloc(totalSize*F.sizeof)[0..totalSize*F.sizeof];

                if (dat != null)
                        for(int i = 0; i < dat.length; i++)
                                (cast(typeof(dat))data)[i] = dat[i];

    }

        ref auto opIndex()
        {
                return data;
        }

// Index a single element, e.g., data[0, 1] or takes a slice/view of the array and returns that as another sMArray
    ref auto opIndex(T...)(T idx)
        {               
if (T.length != dimensions.length) assert(0, "sMArray invalid indexing!");
                size_t i = 0;
                static foreach(k, t; T)
                {
                        static if (k == 0)
                                i = idx[0];
                        else
                                i += idx[k]*dimensions[k-1];
                }

debug { if (i >= data.length) assert(0, "sMArray invalid index! Too Large."); }
                return (cast(F[])data)[i];
        }

// Support for `x..y` notation in slicing operator for the given dimension.
    size_t opSlice(size_t dim)(size_t start, size_t end)
                in { assert(start >= 0 && end <= this.opDollar!dim); }
    body
    {
        return [start, end];
    }

        size_t GetDim(int i)
        {
                return dimensions[i];
        }

        // Support `$` in slicing notation, e.g., arr[1..$, 0..$-1].
@property size_t opDollar(size_t dim)() { return dimensions[dim]; }





        ~this()
        {
                free(data.ptr);
        }



}

Reply via email to