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