[Issue 7753] Support opIndexCreate as part of index operator overloading in user-defined types

d-bugmail at puremagic.com d-bugmail at puremagic.com
Thu Feb 27 21:27:10 UTC 2020


https://issues.dlang.org/show_bug.cgi?id=7753

--- Comment #8 from Steven Schveighoffer <schveiguy at yahoo.com> ---
Just wanted to post something here.

The call a[b][c][d] = 0 results in different calls (_aaGetY now) than x =
a[b][c][d] (_aaGetRvalueX).

So I think H S Teoh is onto the right path. Having a different opIndex
available for assignment (or lvalue manipluation) makes sense and should be
straightforward to define.

Now, to define this a little more concretely, I think opIndexCreate should ONLY
be used when the entire chain of indexing results in a definite lvalue
requirement. This means ONLY opIndexCreate (or AA usage) available in the
expression, and the final "call" should be an opAssign or opOpAssign or
opIndexOpAssign. I would also throw in opUnary that expects mutation (i.e. ++
or --) because it's currently supported by AAs.

Unfortunately, the existing behavior is somewhat inconsistent:

struct S {
  int x;
  void opUnary(string s : "++")() {++x;}
}

S[int][int] aa;

aa[1][1] = S(1); // ok
aa[2][2].x = 5; // range violation
++aa[3][3]; // range violation

int[int] aa2;

aa2[4] += 3; // ok
++aa2[5]; // ok

void foo(ref int x)

foo(aa2[6]); // range violation

So there is not 100% consistency here. The most rational logical implementation
would just require lvalue usage. But the reality is different.

Also note that ++aa[5] does not match ANY operator that would be on the type of
aa. There is no opIndexOpUnary akin to opIndexOpAssign. And it doesn't work if
your underlying type supports ++. That is an inconsistency that will be tough
to duplicate.

--


More information about the Digitalmars-d-bugs mailing list