On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote:
[...]
Oh yes, that is what happens. I was trying to be a little
concise.
You are correct, this is what the code will look in the gory
details (I believe) :
```d
auto x = (auto e = i.opIndex(1), i.opIndexUnary("++")(1)/*this
may or may not expand to what you wrote, not sure what the
compiler does, although what you say does sound like the
obvious thing to do*/, return e);
```
I did indeed override opIndex() but since i need to apply a
bit mask and do some shifting I can't return anything by ref.
As I mentioned, maybe the bit manipulation library could
help(although they don't seem to be overloading the operators
in the first place, thus sidestepping the problem you
encountered).
The only way, for me, to explain the error message ```opIndex
isn't an lvalue and can't be modified.``` for ```i[1]++``` is
that the compiler rewrites to
```D
(auto e = i.opIndex(1), i.opIndex(1).opUnary!"++"()/*1) note: not
opIndexUnary*/, return e;)
```
If it were using ```opIndexUnary``` at 1) it would work.
The gist of it
```D
part_int_t!("alpha", 1, "beta", 4, "gamma", 16) a;
struct part_int_t(ARGS...)
{
int _int;
mixin(generatePartInt!ARGS);
}
// auto-generated from ARGS
alias typeof_alpha = bool;
enum ulong offset_alpha = 0;
enum ulong mask_alpha = 0xFFFF;
// etc.
//getter
@property const pure nothrow @nogc typeof_alpha alpha() {
if (_int & signmask_alpha)
return cast(typeof(return))(((_int & mask_alpha) >>
offset_alpha) | signpad_alpha);
else
return cast(typeof(return))((_int & mask_alpha) >>
offset_alpha);
}
// setter
// ...
const pure nothrow @nogc auto opIndex(size_t _i) {
switch (_i) {
default:
assert (0, "Out of bounds.");
// cases are auto generated from ARGS and mixed in like this
case 0:
return alpha;
case 1:
return beta;
case 2:
return gamma;
}}
// OpIndexAssign, etc.
pure nothrow @nogc auto opIndexUnary(string op)(size_t _i) {
switch (_i) {
default:
assert (0, "Out of bounds.");
// cases are auto generated from ARGS and mixed in like this
case 0:
typeof_alpha result;
auto tmp = prepare_for_op!(op, "alpha");
mixin(op ~ "tmp");
result = finalize!(op, "alpha")(tmp);
return result;
// ...
}}
// repeat for beta and gamma
```
I'll revisit the bitfields in std.bitmanip but there were
shortcomings which prompted me to start ```part_int_t```.