The difference between T[] opIndex() and T[] opSlice()

Salih Dincer salihdb at hotmail.com
Mon Oct 2 06:23:47 UTC 2023


On Monday, 2 October 2023 at 02:01:34 UTC, Jonathan M Davis wrote:
> 
> For most code, you'd just write an opIndex with a single 
> parameter for indexing an element, opSlice with two parameters 
> for slicing the range or container, and then either opIndex or 
> opSlice with no parameters to return a slice of the entire 
> container (in which case, personally, I'd use opSlice, because 
> semantically, that's what you're doing, but either should work 
> IIRC).

Overloading has nothing to do with indexing, so I'll use opSlice.

```d
import std.stdio;
import std.range;

struct Matrix(T)
{
   private T[][] elements;
   size_t length;
   T* ptr;

   this(size_t length)
   {
     this.length = length * length;
     size_t m = T.sizeof * this.length;
     ubyte[] arr = new ubyte[](m);

     ptr = cast(T*)arr.ptr;
     m /= length;

     foreach(i; 0 .. length)
     {
       size_t n = i * m;
       elements ~= cast(T[])arr[n .. n + m];
     }
   }

   ref T opIndex(size_t i)
   in(i < length)
     => ptr[i];

   auto opDollar() => length;
   auto opSliceAssign(T value, size_t a, size_t b)
   in(a <= length && b <= length)
     => ptr[a..b] = value;

   auto opSlice() => elements;
   auto opSliceAssign(T value)
   {
     foreach(i; 0 .. length)
     {
       ptr[i] = value;
     }
   }
}

void main()
{
   auto arr = Matrix!double(3);
   size_t n;

   foreach(value; iota(0.1, 1, 0.1))
     arr[n++] = value;
   
   arr[].writefln!"%-(%-(%s %)\n%)\n";
   
   arr[0..$/2] = 0;   // reset a slice

   arr[].writefln!"%-(%-(%s %)\n%)\n";

   arr[] = 0;             // reset all
   
   arr[].writefln!"%-(%-(%s %)\n%)\n";
   
   arr[6..9] = 1;       // set a slice
   arr[].writefln!"%-(%-(%s %)\n%)\n";
}
```

SDB at 79


More information about the Digitalmars-d-learn mailing list