Straight Forward Arrays

Steven Schveighoffer schveiguy at gmail.com
Sun Oct 1 17:21:32 UTC 2023


On 10/1/23 10:34 AM, Steven Schveighoffer wrote:

> 
> The complexity is from the way d does operator overloading and indexing.
> 
> It should be pretty straightforward. I’ll see if I can post a simple 
> wrapper.

I didn't tackle any attribute or memory safety issues, or many operator 
overloads, but this is going to be reasonably close. It should make a 
copy of the data when copied.

Note this still uses the GC for storage, and when expanding, uses the GC 
to fetch the capacity (this could be done in one call, but meh).

Some niceties of builtin arrays may not work, but this is somewhat of 
the cost you pay for trying to make a custom type.

```d
struct VTArray(T)
{
     private T[] _storage;
     private size_t _length;

     const size_t length() => _length;

     void length(size_t newLen) {
         if(newLen <= _storage.length)
             _length = newLen;
         else
         {
             _storage.length = newLen;
             _storage.length = _storage.capacity;
         }
     }

     inout this(ref inout(VTArray) other)
     {
         this(other[]);
     }

     inout this(inout(T)[] buf)
     {
         auto x = buf.dup;
         x.length = x.capacity;
         _length = buf.length;
         _storage = cast(inout)x;
     }

     ref inout(T) opIndex(size_t idx) inout {
         assert(idx < length);
         return _storage[idx];
     }

     void opOpAssign(string s : "~", V)(auto ref V other) {
         static if(is(V == T[]))
         {
             immutable avail = _storage.length - length;
             if(avail < other.length)
             {
                 _storage[length .. $] = other[0 .. avail];
                 _storage ~= other[avail .. $];
                 _storage.length = _storage.capacity; // expand to capacity;
             }
             else
             {
                 _storage[length .. length + other.length] = other;
             }
             _length += other.length;
         }
         else static if(is(V == T))
         {
             if(length == _storage.length)
             {
                 _storage.length += 1;
                 _storage.length = _storage.capacity;
             }
             _storage[_length++] = other;
         }
         else static if(is(V == VTArray))
         {
             this ~= other[];
         }
     }

     void opAssign(T[] arr)
     {
         _storage = arr.dup;
         _storage.length = _storage.capacity;
         _length = arr.length;
     }

     void opAssign(VTArray vtarr)
     {
         this = vtarr._storage[0 .. vtarr.length];
     }

     inout(T)[] opIndex() inout => _storage[0 .. _length];

     void toString(Out)(auto ref Out output)
     {
         import std.format;
         formattedWrite(output, "%s", this[]);
     }
}

void main()
{
     auto arr = VTArray!int.init;
     arr ~= 1;
     arr ~= [2,3,4,5];
     import std.stdio;
     writeln(arr);
     auto arr2 = arr;
     arr2[0] = 5;
     writeln(arr);
     writeln(arr2);
     arr2 ~= arr;
     writeln(arr2);
}
```

This should give you a reasonable head-start.

-Steve


More information about the Digitalmars-d-learn mailing list