Comment #0 by andrej.mitrovich — 2012-04-29T23:26:40Z
Currently properties are only usable for reading and writing values, but they can't really be used for in-place modification:
// fake int type, just to avoid rvalue errors in this demo
struct Bar { int x; alias x this; }
struct Foo
{
Bar _val;
@property Bar val() { return _val; }
@property void val(Bar nval) { _val = nval; }
}
void main()
{
Foo foo;
foo.val += 5; // modifies *temporary*, then discards it
foo.val++; // ditto
}
The only way to work around this is to make the getter property return by ref, but this completely circumvents the setter property, e.g.:
struct Bar { int x; alias x this; }
struct Foo
{
Bar _val;
@property ref Bar val() { return _val; }
@property void val(Bar nval) { _val = nval; } // never called
}
void main()
{
Foo foo;
foo.val += 5;
assert(foo.val == 5); // updated, but setter circumvented
foo.val++;
assert(foo.val == 6); // ditto
}
C# apparently implements in-place modification by translating calls such as this:
foo.val += 5;
foo.val++;
into this:
foo.val = foo.val + 5;
foo.val = foo.val + 1;
DIP4 also mentioned this feature (http://www.prowiki.org/wiki4d/wiki.cgi?LanguageDevel/DIPs/DIP4), but was superseeded by DIP6 which was approved. I think we ought to implement this to make properties more usable and less error-prone to work with.
Comment #1 by smjg — 2012-05-07T04:06:21Z
*** Issue 8056 has been marked as a duplicate of this issue. ***
Comment #2 by jminer7 — 2012-05-15T18:40:33Z
This bug might be a duplicate of bug 808, although @property didn't exist back then. This bug has a more detailed description.
I would really like to see this implemented. Properties seem only half-implemented to me if they don't support +=, -=, etc. operators.
Comment #3 by doob — 2013-01-24T23:42:16Z
Same thing if you do something like this:
foo.val.x = 3;
Needs to be rewritten to:
auto __tmp = foo.val;
__tmp.x = 3;
foo.val = __tmp;
Comment #4 by greensunny12 — 2016-06-20T22:41:52Z
Issue 16187 (bitmanip fields should be lvalues) depends on this. Has anyone worked on implementing this lowering on the DMD frontend?
Comment #5 by abc.mikey — 2016-10-09T12:23:58Z
As a beginner this is a source of some confusion for me. Ideally the implementation details of a property vs a member variable should be transparent to me as a user of a given object.
class Test {
private:
int _val, _val2;
public:
@property int val() { return _val; }
@property void val(int val) { _val = val; }
@property auto ref val2() { return _val2; }
}
void main() {
auto t = new Test;
//t.val += 100; // BAD - not an lvalue
t.val(t.val + 100); // probably preferable to misleading syntax
t.val2 += 200; // OK - but inconsistent
import std.stdio : writefln;
writefln("val: %d, val2: %d", t.val, t.val2);
}
~