Why is opIndexAssign replaced by opSlice here?

Paul Backus snarwin at gmail.com
Mon Oct 18 03:42:35 UTC 2021


On Sunday, 17 October 2021 at 22:52:27 UTC, Elmar wrote:
> Hello Dear community.
>
> I'd like to overload `opIndexAssign` for a struct which wraps 
> around a generic array (so that it can't support `opIndex` due 
> to unknown return type).
>
> Broken down as much as possible this is the code:
>
> ```
> import std.stdio : writeln;
> import std.range : ElementType;
>
> struct S {
> 	void opIndexAssign(X, RANGE)(X x, RANGE range)
> 		if (is(ElementType!RANGE : size_t))
> 	{
> 		writeln(__FUNCTION__);
> 	}
>
> 	auto opSlice(size_t start, size_t end) {
> 		import std.range : iota;
> 		return iota(start, end);
> 	}
> }
>
> void main()
> {
> 	auto arr = new int[7];
>
> 	S s;
> 	s.opIndexAssign(arr, s.opSlice(1,4));  // works
> 	s[0..3] = arr[1..4];  // does not work, compiles to 
> `s.opSlice(0,3) = arr[1..4]`
> }
> ```
>
> I'm clueless about why it wouldn't compile the last statement 
> to `s.opIndexAssign(arr[1..4], s.opSlice(0,3))`.
>
> Help appreciated :-)

What happens here is, the compiler first tries the D2-style 
rewrite:

```d
s.opIndexAssign(arr[1..4], s.opSlice!0(0, 3))
```

However, that rewrite fails to compile, because your `opSlice` 
does not take a template argument specifying the dimension along 
which to slice, as specified in the language spec's section on 
["Slice Operator Overloading".][1]

Since the above rewrite fails to compile, it falls back to 
rewriting the expression using D1-style operator overloads:

> For backward compatibility, `a[]` and `a[i..j]` can also be 
> overloaded by implementing `opSlice()` with no arguments and 
> `opSlice(i, j)` with two arguments, respectively. This only 
> applies for one-dimensional slicing, and dates from when D did 
> not have full support for multidimensional arrays. This usage 
> of opSlice is discouraged.

...which results in the following rewritten statement:

```d
s.opSlice(0, 3) = arr[1..4];
```

My guess is that you got into this situation by trying to follow 
the example in the spec's section on ["Slice Assignment Operator 
Overloading"][2]. Unfortunately, that example is incorrect.

Here is a fixed version of your example on run.dlang.io: 
https://run.dlang.io/is/dtfT5y

[1]: https://dlang.org/spec/operatoroverloading.html#slice
[2]: 
https://dlang.org/spec/operatoroverloading.html#slice_assignment_operator


More information about the Digitalmars-d-learn mailing list