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@79

Reply via email to