Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 15:39:59 UTC, Tejas wrote: On Thursday, 15 July 2021 at 13:28:19 UTC, wjoe wrote: On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote: [...] 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. [...] Sucks :( I really can't spend more time on this, hope things work out for you somehow. Best of luck Regards Tejas No worries. Your time is very much appreciated.
Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 13:28:19 UTC, wjoe wrote: On Thursday, 15 July 2021 at 12:09:20 UTC, Tejas wrote: [...] 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. [...] Sucks :( I really can't spend more time on this, hope things work out for you somehow. Best of luck Regards Tejas
Re: opIndexUnary post in-/decrement how to ?
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 = 0x; // 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```.
Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 11:02:17 UTC, wjoe wrote: On Thursday, 15 July 2021 at 04:07:49 UTC, Tejas wrote: Your code ```d auto x = i[1]++; ``` Expands to: ```d auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice opIndexUnary*/, return e;); ``` This doesn't happen with pre increment. No compiler shenanigans. Interesting to see it spelt out like this (your remarks are very enlightening) so I just went one step further and rewrote this line like so: ```D i[1] = 3; auto x = (){auto e = i[1]; ++i[1]; return e;}(); assert (i[1] == 4 && x == 3); ``` This just works. But I don't think this is what happens. What I think happens is that the compiler rewrites ```i[1]++`` to something like this: ```D i.opIndex(1).opUnary!"++"(); ``` plus all the other shenanigans. 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).
Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 04:07:49 UTC, Tejas wrote: Your code ```d auto x = i[1]++; ``` Expands to: ```d auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice opIndexUnary*/, return e;); ``` This doesn't happen with pre increment. No compiler shenanigans. Interesting to see it spelt out like this (your remarks are very enlightening) so I just went one step further and rewrote this line like so: ```D i[1] = 3; auto x = (){auto e = i[1]; ++i[1]; return e;}(); assert (i[1] == 4 && x == 3); ``` This just works. But I don't think this is what happens. What I think happens is that the compiler rewrites ```i[1]++`` to something like this: ```D i.opIndex(1).opUnary!"++"(); ``` plus all the other shenanigans. 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.
Re: opIndexUnary post in-/decrement how to ?
On Thursday, 15 July 2021 at 04:01:15 UTC, Tejas wrote: I'm so sorry all this was basically useless for you. I can't spend more time on this, so as a last resort I leave you this: https://dlang.org/phobos/std_bitmanip.html This is the official bit manipulation standard library, maybe it will help you in some way; the ```bitfield``` struct looked mighty familiar to your ```part_int``` struct, but maybe that's my cognitive bias, you should verify it. Best of luck! Oh no it wasn't useless at all. The time and effort you put into this is very much appreciated and that of everyone else, too.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 20:55:32 UTC, wjoe wrote: In my particular case the compiler can rule out ```opIndex``` so why does it abort instead of trying ```opIndexUnary``` ? Or was it trying and it didn't work ? If that's the case I'd like to know the reason why it discarded ```opIndexUnary```. Anyways all the answers so far are much appreciated! Your code ```d auto x = i[1]++; ``` Expands to: ```d auto x = (auto e = i[1]/*notice opIndex*/, ++i[1]/* notice opIndexUnary*/, return e;); ``` This doesn't happen with pre increment. No compiler shenanigans. Hence your problems. Please take a look at the library I mentioned previously, it may help.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 20:55:32 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 16:13:35 UTC, Tejas wrote: [...] Congratulations:) Unfortunately I haven't got anything I could return by ref so I can't take advantage of a low hanging fruit. In my book overloading operators is no fun - at all - and always a last resort because it requires so much time and testing and causes so many headaches. Workarounds exist like ```i[n] += 1``` or direct call via ```i.opIndexUnary!"++"(n)``` or simply ```++i[n]```. But that's beside the point. There's nothing in the spec that says something about something needs to be returned by ref. Rewriting manually compiles and works as intended. So clearly something else is going on which makes the compiler select ```opIndex``` over ```opIndexUnary``` rewriting it post to pre. In my particular case the compiler can rule out ```opIndex``` so why does it abort instead of trying ```opIndexUnary``` ? Or was it trying and it didn't work ? If that's the case I'd like to know the reason why it discarded ```opIndexUnary```. Anyways all the answers so far are much appreciated! I'm so sorry all this was basically useless for you. I can't spend more time on this, so as a last resort I leave you this: https://dlang.org/phobos/std_bitmanip.html This is the official bit manipulation standard library, maybe it will help you in some way; the ```bitfield``` struct looked mighty familiar to your ```part_int``` struct, but maybe that's my cognitive bias, you should verify it. Best of luck!
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 16:13:35 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 15:08:56 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote: On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: [...] It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value. [...] That makes a lot of sense now, thank you! **IT WORKS NOW** Thanks vit for the ```ref``` idea! ```d import std.stdio; struct abc{ int[100] a; static int temp; ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE RETURN*/ { return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; writeln(s[0]++);// doesn't work for some reason EDIT: IT NOW WORKS writeln(s[0]); writeln(++s[0]); // writeln(s++);//but this works!! // writeln(s); } ``` Congratulations:) Unfortunately I haven't got anything I could return by ref so I can't take advantage of a low hanging fruit. In my book overloading operators is no fun - at all - and always a last resort because it requires so much time and testing and causes so many headaches. Workarounds exist like ```i[n] += 1``` or direct call via ```i.opIndexUnary!"++"(n)``` or simply ```++i[n]```. But that's beside the point. There's nothing in the spec that says something about something needs to be returned by ref. Rewriting manually compiles and works as intended. So clearly something else is going on which makes the compiler select ```opIndex``` over ```opIndexUnary``` rewriting it post to pre. In my particular case the compiler can rule out ```opIndex``` so why does it abort instead of trying ```opIndexUnary``` ? Or was it trying and it didn't work ? If that's the case I'd like to know the reason why it discarded ```opIndexUnary```. Anyways all the answers so far are much appreciated!
Re: opIndexUnary post in-/decrement how to ?
On 7/14/21 11:27 AM, Tejas wrote: > the compiler error should have been a dead giveaway > that opIndex was returning a _constant_ value I know you mean "rvalue" but if I may be unnecessarily pedantic, an rvalue can indeed be mutated: struct A { int i; void mutate() { i = 42; import std.stdio; writeln("I am not constant. :)"); } } struct B { auto opUnary(string op)() { return A(); } } void main() { auto b = B(); (++b).mutate(); // <-- Mutating an rvalue } Ali
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 17:42:03 UTC, Ali Çehreli wrote: On 7/14/21 9:13 AM, Tejas wrote: > ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE > RETURN*/ { Indeed... I cover that 'ref' here: http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator Two quotes from that section: 1) "it is advisable to observe the return type of the same operator on fundamental types." NOTE: I agree that for that to make sense, one needs to know the "return type" of fundamental type operations. It may not be clear that ++i is a reference to 'i' ("i itself"): void main() { int i; ++i = 42; assert(i == 42); } 2) "With the exception of opAssign, it is recommended that the operators that modify the object return the object itself. [...] The return type is the type of the struct, marked by the ref keyword to mean reference." Ali To be honest even the compiler error should have been a dead giveaway that opIndex was returning a _constant_ value and the ```++``` operator can't operate on that... I should've taken the diagnostic to heart and not just tried to brute force my way through the problem. Obviously, I retract my statement that this might be a compiler bug.
Re: opIndexUnary post in-/decrement how to ?
On 7/14/21 9:13 AM, Tejas wrote: > ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE > RETURN*/ { Indeed... I cover that 'ref' here: http://ddili.org/ders/d.en/operator_overloading.html#ix_operator_overloading.return%20type,%20operator Two quotes from that section: 1) "it is advisable to observe the return type of the same operator on fundamental types." NOTE: I agree that for that to make sense, one needs to know the "return type" of fundamental type operations. It may not be clear that ++i is a reference to 'i' ("i itself"): void main() { int i; ++i = 42; assert(i == 42); } 2) "With the exception of opAssign, it is recommended that the operators that modify the object return the object itself. [...] The return type is the type of the struct, marked by the ref keyword to mean reference." Ali
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 15:08:56 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote: On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: [...] It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value. [...] That makes a lot of sense now, thank you! **IT WORKS NOW** Thanks vit for the ```ref``` idea! ```d import std.stdio; struct abc{ int[100] a; static int temp; ref/*notice this ref*/ int opIndex(int index)return/*NOTICE THE RETURN*/ { return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; writeln(s[0]++);// doesn't work for some reason EDIT: IT NOW WORKS writeln(s[0]); writeln(++s[0]); // writeln(s++);//but this works!! // writeln(s); } ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote: On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote: ```d import std.stdio; struct abc{ int[100] a; struct Proxy{ abc* ptr; const int index; int opUnary(string op : "++")(){ return ++ptr.a[index]; //add missing ++ } } Proxy opIndex(int index)return{ return Proxy(&this, index); } } void main (){ abc s; s[0]++; ++s[0]; } ``` I tried changing ```s[0]++``` to ``` s[0] += 1``` the same lvalue problem arose :( ``` Error: `s.opIndex(0)` is not an lvalue and cannot be modified ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 15:23:05 UTC, vit wrote: On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote: ```d import std.stdio; struct abc{ int[100] a; struct Proxy{ abc* ptr; const int index; int opUnary(string op : "++")(){ return ++ptr.a[index]; //add missing ++ } } Proxy opIndex(int index)return{ return Proxy(&this, index); } } void main (){ abc s; s[0]++; ++s[0]; } ``` The ```post increment``` still doesn't work :( this is the output for your code: ``` Proxy(7FFC7ACB3E60, 0) 2 ``` And if the add the following statements: ```d writeln(s[0]++); writeln(s[0]); writeln(s[0]++); writeln(s[0]); writeln(++s[0]); ``` Output: ``` Proxy(7FFCBE3CAF20, 0) Proxy(7FFCBE3CAF20, 0) Proxy(7FFCBE3CAF20, 0) Proxy(7FFCBE3CAF20, 0) 3 ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 15:19:03 UTC, vit wrote: ```d import std.stdio; struct abc{ int[100] a; struct Proxy{ abc* ptr; const int index; int opUnary(string op : "++")(){ return ++ptr.a[index]; //add missing ++ } } Proxy opIndex(int index)return{ return Proxy(&this, index); } } void main (){ abc s; s[0]++; ++s[0]; } ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote: On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote: On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: [...] From doc: https://dlang.org/spec/operatoroverloading.html Postincrement e++ and Postdecrement e-- Operators These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators: Postfix Operator Rewrites op rewrite e-- (auto t = e, --e, t) e++ (auto t = e, ++e, t) Rewriting part doesn't work with operator overloading. If the rewriting part doesn't work with over This work: ```d import std.stdio; struct abc{ int[100] a; ref int opIndex(int index)return{ return a[index]; } } void main (){ abc s; s[0]++; ++s[0]; } ``` Oh... since it was asking for an lvalue, you just passed it by reference... seems so obvious in hindsight... Nice. Pity it doesn't seem to solve OP's problem.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 15:01:45 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote: On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote: [...] This work: ```d import std.stdio; struct abc{ int[100] a; ref int opIndex(int index)return{ return a[index]; } } void main (){ abc s; s[0]++; ++s[0]; } ``` This does work for that example but I can't return by reference because what I'm operating on is a part of an int. Some context: ```D struct part_int_t(ARGS...) { int _int; mixin(generate_parts!ARGS); } alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, "index", 23); handle_t handle; static assert (is(handle.typeof_isAllocated): bool)); static assert (is(handle.typeof_gen): ubyte)); static assert (is(handle.typeof_index): uint)); handle[2] = true; handle.gen = 1; handle.index = 1234; assert (handle.isAllocated); assert (handle.gen = 1); assert (handle[0] = 1234); handle++; assert (handle.index == 1235); handle.gen++; assert (handle.gen == 2); handle.reset(); assert (!handle.isAllocated); assert (handle.gen = 3); assert (handle.index = 0); ``` generate_parts!ARGS produces bit masks, getters, setters, opIndex/OpAssign/Unary, etc. and it's impossible to return bits 0-26 of _int by ref. Try something like this: ```d import std.stdio; struct abc{ int[100] a; struct Proxy{ abc* ptr; const int index; int opUnary(string op : "++")(){ return ptr.a[index]; } } Proxy opIndex(int index)return{ return Proxy(&this, index); } } void main (){ abc s; s[0]++; ++s[0]; } ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 14:50:01 UTC, Mike Parker wrote: On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: [...] It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value. [...] That makes a lot of sense now, thank you!
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 14:39:03 UTC, vit wrote: On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote: On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: [...] From doc: https://dlang.org/spec/operatoroverloading.html Postincrement e++ and Postdecrement e-- Operators These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators: Postfix Operator Rewrites op rewrite e-- (auto t = e, --e, t) e++ (auto t = e, ++e, t) Rewriting part doesn't work with operator overloading. If the rewriting part doesn't work with overloading then why aren't we allowed to explicitly overload ```post-increment/decrement``` operators? How else will the OP solve their problem? It must rewrite, otherwise it's impossible (I think). This work: ```d import std.stdio; struct abc{ int[100] a; ref int opIndex(int index)return{ return a[index]; } } void main (){ abc s; s[0]++; ++s[0]; } ``` This does work for that example but I can't return by reference because what I'm operating on is a part of an int. Some context: ```D struct part_int_t(ARGS...) { int _int; mixin(generate_parts!ARGS); } alias handle_t = part_int_t!("isAllocated", 1, "gen", 8, "index", 23); handle_t handle; static assert (is(handle.typeof_isAllocated): bool)); static assert (is(handle.typeof_gen): ubyte)); static assert (is(handle.typeof_index): uint)); handle[2] = true; handle.gen = 1; handle.index = 1234; assert (handle.isAllocated); assert (handle.gen = 1); assert (handle[0] = 1234); handle++; assert (handle.index == 1235); handle.gen++; assert (handle.gen == 2); handle.reset(); assert (!handle.isAllocated); assert (handle.gen = 3); assert (handle.index = 0); ``` generate_parts!ARGS produces bit masks, getters, setters, opIndex/OpAssign/Unary, etc. and it's impossible to return bits 0-26 of _int by ref.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Yes I saw that, and I suppose it would work just fine if it were rewritten to just ```++i[1]```. What I'm struggling to understand is the ```{auto a = i[1], ... ,a}``` part. I can't parse that. What's up with the assignment and the comma stuff ? It's how the contract of post-inc/dec work---pre-inc/dec return the modified value, post-inc/dec return the original value. ```d int i = 1; assert(++i == 2); int j = 1; assert(j++ == 1); ``` The rewrite of the compiler is done in such a way that the result of the expression is the original value. That's what the commas are for. ``` So you can parse that rewrite example as it if were a function, with each expression separated by a comma, and the final expression the result: ```d int postInc(ref int j) { auto a = j; ++j; return a; } ``` It doesn't actually create a function, but this demonstrates the effect. So that's why you don't have to worry about postfix/prefix for these. The compiler handles that behind the scenes. All you need to worry about is returning the incremented value.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: I think it's a bug, because the following works: ```d import std.stdio; struct abc{ int[100] a; int opIndex(int index){ return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; int[100] a; int temp; writeln (a[20]++); writeln(a[20]); writeln(++s[20]); writeln(s[20]); //writeln(s[0]++);// doesn't work for some reason writeln(s[0]); writeln(s++);//but this works!! writeln(s); } ``` ```D writeln(++s[0]); // should work writeln(s++); // this calls opUnary if I'm not mistaken ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 13:16:49 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote: On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: [...] From doc: https://dlang.org/spec/operatoroverloading.html Postincrement e++ and Postdecrement e-- Operators These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators: Postfix Operator Rewrites op rewrite e-- (auto t = e, --e, t) e++ (auto t = e, ++e, t) Rewriting part doesn't work with operator overloading. If the rewriting part doesn't work with overloading then why aren't we allowed to explicitly overload ```post-increment/decrement``` operators? How else will the OP solve their problem? It must rewrite, otherwise it's impossible (I think). This work: ```d import std.stdio; struct abc{ int[100] a; ref int opIndex(int index)return{ return a[index]; } } void main (){ abc s; s[0]++; ++s[0]; } ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 13:09:56 UTC, vit wrote: On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Yes I saw that, and I suppose it would work just fine if it were rewritten to just ```++i[1]```. What I'm struggling to understand is the ```{auto a = i[1], ... ,a}``` part. I can't parse that. What's up with the assignment and the comma stuff ? I think it's a bug, because the following works: ```d import std.stdio; struct abc{ int[100] a; int opIndex(int index){ return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; int[100] a; int temp; writeln (a[20]++); writeln(a[20]); writeln(++s[20]); writeln(s[20]); //writeln(s[0]++);// doesn't work for some reason writeln(s[0]); writeln(s++);//but this works!! writeln(s); } ``` From doc: https://dlang.org/spec/operatoroverloading.html Postincrement e++ and Postdecrement e-- Operators These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators: Postfix Operator Rewrites op rewrite e-- (auto t = e, --e, t) e++ (auto t = e, ++e, t) Rewriting part doesn't work with operator overloading. If the rewriting part doesn't work with overloading then why aren't we allowed to explicitly overload ```post-increment/decrement``` operators? How else will the OP solve their problem? It must rewrite, otherwise it's impossible (I think).
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 12:49:58 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Yes I saw that, and I suppose it would work just fine if it were rewritten to just ```++i[1]```. What I'm struggling to understand is the ```{auto a = i[1], ... ,a}``` part. I can't parse that. What's up with the assignment and the comma stuff ? I think it's a bug, because the following works: ```d import std.stdio; struct abc{ int[100] a; int opIndex(int index){ return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; int[100] a; int temp; writeln (a[20]++); writeln(a[20]); writeln(++s[20]); writeln(s[20]); //writeln(s[0]++);// doesn't work for some reason writeln(s[0]); writeln(s++);//but this works!! writeln(s); } ``` From doc: https://dlang.org/spec/operatoroverloading.html Postincrement e++ and Postdecrement e-- Operators These are not directly overloadable, but instead are rewritten in terms of the ++e and --e prefix operators: Postfix Operator Rewrites op rewrite e-- (auto t = e, --e, t) e++ (auto t = e, ++e, t) Rewriting part doesn't work with operator overloading.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: On Wednesday, 14 July 2021 at 10:07:38 UTC, wjoe wrote: I'm want to do something like this ```D part_int_t!(1,2,3) i; auto x = -i[0]; --i[1]; // 1 i[1]++; // 2 ``` I think the operator I need to overload would be opIndexUnary which I did. (1) compiles. (2) doesn't - the compiler complains that i.opIndex isn't an lvalue and can't be modified. The language spec says that Post in- and decrement are rewritten but something's fishy. What's going on behind the scene and how can I make it work? Please check the language spec here: https://dlang.org/spec/operatoroverloading.html#postincrement_postdecrement_operators You can't directly overload the postincrement operator. You need to rewrite it like: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Ignore this, I wanted to say that this is what the _compiler_ rewrites it to when _you_ write ```i[1]++``` There is no way to explicitly overload the ```post increment``` operator because of this.
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 12:35:07 UTC, wjoe wrote: On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Yes I saw that, and I suppose it would work just fine if it were rewritten to just ```++i[1]```. What I'm struggling to understand is the ```{auto a = i[1], ... ,a}``` part. I can't parse that. What's up with the assignment and the comma stuff ? I think it's a bug, because the following works: ```d import std.stdio; struct abc{ int[100] a; int opIndex(int index){ return a[index]; } int opIndexUnary(string s)(int index) if(s == "++"){ return ++a[index]; } int[] opUnary(string s)() if (s == "++"){ return a[] += 1; } } void main (){ abc s; int[100] a; int temp; writeln (a[20]++); writeln(a[20]); writeln(++s[20]); writeln(s[20]); //writeln(s[0]++);// doesn't work for some reason writeln(s[0]); writeln(s++);//but this works!! writeln(s); } ```
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 11:31:36 UTC, Tejas wrote: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete. Yes I saw that, and I suppose it would work just fine if it were rewritten to just ```++i[1]```. What I'm struggling to understand is the ```{auto a = i[1], ... ,a}``` part. I can't parse that. What's up with the assignment and the comma stuff ?
Re: opIndexUnary post in-/decrement how to ?
On Wednesday, 14 July 2021 at 10:07:38 UTC, wjoe wrote: I'm want to do something like this ```D part_int_t!(1,2,3) i; auto x = -i[0]; --i[1]; // 1 i[1]++; // 2 ``` I think the operator I need to overload would be opIndexUnary which I did. (1) compiles. (2) doesn't - the compiler complains that i.opIndex isn't an lvalue and can't be modified. The language spec says that Post in- and decrement are rewritten but something's fishy. What's going on behind the scene and how can I make it work? Please check the language spec here: https://dlang.org/spec/operatoroverloading.html#postincrement_postdecrement_operators You can't directly overload the postincrement operator. You need to rewrite it like: ``` {auto a = i[1] , ++i[1] , a} //note the , not the ;``` Sorry I can't provide something even more concrete.