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

Steven Schveighoffer schveiguy at gmail.com
Tue Oct 3 13:07:00 UTC 2023


On Monday, 2 October 2023 at 20:42:14 UTC, Paul Backus wrote:
> On Monday, 2 October 2023 at 20:34:11 UTC, Salih Dincer wrote:
>> In an old version (for example, v2.0.83), the code you 
>> implemented in the places where Slice is written above works 
>> as desired.  In the most current versions, the parameterized 
>> opIndexAssign(T value) gives the error:
>>
>>> onlineapp.d(51): Error: function 
>>> `onlineapp.Matrix!double.Matrix.opIndexAssign(double value)` 
>>> is not callable using argument types `(double, ulong)`
>>> onlineapp.d(51):        expected 1 argument(s), not 2
>>
>> **Source:** https://run.dlang.io/is/TPAg5m
>
> I don't know what's wrong in your example but this works for me:
>
> ```d
> struct S
> {
>     void opIndexAssign(int value)
>     {
>         import std.stdio;
>         writeln("assigned ", value);
>     }
> }
>
> void main()
> {
>     S s;
>     s[] = 7;
> }
> ```

So in the example linked by Salih, the `opIndex` returns a ref, 
which is a valid mechanism to properly do `a[0] = val;`. However, 
since `opIndexAssign` exists, the compiler expects that to be 
used instead.

Essentially, by naming the slice assign the same operator as 
index assign, you have eliminated the possibility for ref 
assignment via indexing.

Now, you can define a further `opIndexAssign(T val, size_t idx)`. 
However, now you lose capabilities like `a[0]++`, which I don't 
think has a possibility of implementing using an `opIndex` 
operator, and it would be pretty ugly if you had to.

This seems like a design flaw in the `opIndex` overloading 
changes. I would stick with `opSliceAssign` if faced with this 
problem (glad it still works!)

It could also be considered a bug but I don't know the overload 
implications.

-Steve


More information about the Digitalmars-d-learn mailing list