digitalmars.D.learn - re-creating C++'s reference bahavior
- swiftcoder - Tristam MacDonald (11/11) Apr 16 2007 I am fairly new to D, from a C++ background, and I am having a hard time...
- Daniel Keep (19/38) Apr 16 2007 AFAIK, there's really no way to exactly duplicate C++'s references.
- akcom (7/54) Apr 16 2007 What about situations in which you're not just returning a reference to ...
- swiftcoder (4/11) Apr 17 2007 But this comes back to the basic problem:
- Derek Parnell (47/52) Apr 17 2007 Does this below help any?
- swiftcoder (8/73) Apr 17 2007 What it really gets down to, is that I don't want to increase the code c...
- swiftcoder (2/83) Apr 17 2007
- BCS (8/13) Apr 17 2007 If I'm reading you correctly, then the problem is that in this line you ...
- Henning Hasemann (6/6) Apr 17 2007 Maybe you want to take a look at this thread which
I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: class Vector3f; class Node { Vector3f &position(); }; Node n; n.position().x = 0; // Works as expected, sets n.position().x to 0 Vector3f v = n.position(); v.x = 10; // Works as expected in C++ since v is a copy of n.position() But now in D, I find that the last statement requires an explicit copy on the user's part, otherwise they are using the actual instance, and may do nasty things to it unintentionally. The obvious fix is to copy the vector in Node.position(), but then you have lost the benefits of references, namely to modify the variable. So it would seem that the only way to handle this is to return a copy in the getter function, and require explicit setting with the setter method (thus losing constructs such as n.position().x = 0)?
Apr 16 2007
swiftcoder - Tristam MacDonald wrote:I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: class Vector3f; class Node { Vector3f &position(); }; Node n; n.position().x = 0; // Works as expected, sets n.position().x to 0 Vector3f v = n.position(); v.x = 10; // Works as expected in C++ since v is a copy of n.position() But now in D, I find that the last statement requires an explicit copy on the user's part, otherwise they are using the actual instance, and may do nasty things to it unintentionally. The obvious fix is to copy the vector in Node.position(), but then you have lost the benefits of references, namely to modify the variable. So it would seem that the only way to handle this is to return a copy in the getter function, and require explicit setting with the setter method (thus losing constructs such as n.position().x = 0)?AFAIK, there's really no way to exactly duplicate C++'s references. However, if all "position()" is doing is returning a reference to a vector, then do you really need a function at all? If you just use a member variable, then the problem disappears. And incidentally, you can omit the parens with D since it's a function with no arguments. ie:auto v = n.position; v.x = 10;("auto" is used here to trigger type inference -- if you specify a variable's storage class, you can omit the type itself.) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 16 2007
AFAIK, there's really no way to exactly duplicate C++'s references. However, if all "position()" is doing is returning a reference to a vector, then do you really need a function at all? If you just use a member variable, then the problem disappears.What about situations in which you're not just returning a reference to a class object? A templated hash map implementation for example, may want to do something like the D equivalent of template <class T, class K >T &HashMap<T,K>::find( K ) Things become a bit trickier if you're dealing with basic types. "Daniel Keep" <daniel.keep.lists gmail.com> wrote in message news:f0160f$bau$1 digitalmars.com...swiftcoder - Tristam MacDonald wrote:I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: class Vector3f; class Node { Vector3f &position(); }; Node n; n.position().x = 0; // Works as expected, sets n.position().x to 0 Vector3f v = n.position(); v.x = 10; // Works as expected in C++ since v is a copy of n.position() But now in D, I find that the last statement requires an explicit copy on the user's part, otherwise they are using the actual instance, and may do nasty things to it unintentionally. The obvious fix is to copy the vector in Node.position(), but then you have lost the benefits of references, namely to modify the variable. So it would seem that the only way to handle this is to return a copy in the getter function, and require explicit setting with the setter method (thus losing constructs such as n.position().x = 0)?And incidentally, you can omit the parens with D since it's a function with no arguments. ie:auto v = n.position; v.x = 10;("auto" is used here to trigger type inference -- if you specify a variable's storage class, you can omit the type itself.) -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Apr 16 2007
But this comes back to the basic problem: Vector3f v = n.position; v.x = 10; // changes n.position.x, since v is a reference to the same instance as n.position is Daniel Keep Wrote:AFAIK, there's really no way to exactly duplicate C++'s references. However, if all "position()" is doing is returning a reference to a vector, then do you really need a function at all? If you just use a member variable, then the problem disappears.
Apr 17 2007
On Mon, 16 Apr 2007 20:47:31 -0400, swiftcoder - Tristam MacDonald wrote:I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: ... But now in D, I find that the last statement requires ...Does this below help any? //////////////////// import std.stdio; class Vector3f { int x; float y; } class Node { Vector3f m_position; // (reference to) a Vector Vector3f position() // Copy-getter { Vector3f t = new Vector3f; // copy fields by hand t.x = m_position.x; t.y = m_position.y; return t; } Vector3f* position_flds() // Reference-getter { return &m_position; } this() { m_position = new Vector3f; } } void main() { Node n = new Node; writefln("A %s %s", n.position.x, n.position.y); n.position_flds.x = 1; n.position_flds.y = 2.2; writefln("B %s %s", n.position.x, n.position.y); Vector3f v = n.position; writefln("C %s %s", v.x, v.y); v.x = 10; v.y = 9.9; writefln("D %s %s", v.x, v.y); writefln("E %s %s", n.position.x, n.position.y); } /////////////////// -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 17/04/2007 5:30:04 PM
Apr 17 2007
What it really gets down to, is that I don't want to increase the code complexity needlessly. For many reasons, there shouldn't be a copy made when all we want to do is query a member, and we musn't have a copy when we set a member: float x = n.position.x; // or: n.position.x = 10; But we do want a copy when we request the whole vector: Vector3f v = n.position; So maybe the best thing is to override opAssign() to copy (thus behaving like a struct). Then the olnly thing to make sure is that functions taking a vector as an 'in' argument make a local copy rather than modifying the argument directly. And since opAdd, etc. already produce new vectors, I don't think that will be much of a problem. Does this make sense to you? Derek Parnell Wrote:On Mon, 16 Apr 2007 20:47:31 -0400, swiftcoder - Tristam MacDonald wrote:I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: ... But now in D, I find that the last statement requires ...Does this below help any? //////////////////// import std.stdio; class Vector3f { int x; float y; } class Node { Vector3f m_position; // (reference to) a Vector Vector3f position() // Copy-getter { Vector3f t = new Vector3f; // copy fields by hand t.x = m_position.x; t.y = m_position.y; return t; } Vector3f* position_flds() // Reference-getter { return &m_position; } this() { m_position = new Vector3f; } } void main() { Node n = new Node; writefln("A %s %s", n.position.x, n.position.y); n.position_flds.x = 1; n.position_flds.y = 2.2; writefln("B %s %s", n.position.x, n.position.y); Vector3f v = n.position; writefln("C %s %s", v.x, v.y); v.x = 10; v.y = 9.9; writefln("D %s %s", v.x, v.y); writefln("E %s %s", n.position.x, n.position.y); } /////////////////// -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 17/04/2007 5:30:04 PM
Apr 17 2007
Except of course that opAssign is not overload-able in this manner. swiftcoder Wrote:What it really gets down to, is that I don't want to increase the code complexity needlessly. For many reasons, there shouldn't be a copy made when all we want to do is query a member, and we musn't have a copy when we set a member: float x = n.position.x; // or: n.position.x = 10; But we do want a copy when we request the whole vector: Vector3f v = n.position; So maybe the best thing is to override opAssign() to copy (thus behaving like a struct). Then the olnly thing to make sure is that functions taking a vector as an 'in' argument make a local copy rather than modifying the argument directly. And since opAdd, etc. already produce new vectors, I don't think that will be much of a problem. Does this make sense to you? Derek Parnell Wrote:On Mon, 16 Apr 2007 20:47:31 -0400, swiftcoder - Tristam MacDonald wrote:I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++: ... But now in D, I find that the last statement requires ...Does this below help any? //////////////////// import std.stdio; class Vector3f { int x; float y; } class Node { Vector3f m_position; // (reference to) a Vector Vector3f position() // Copy-getter { Vector3f t = new Vector3f; // copy fields by hand t.x = m_position.x; t.y = m_position.y; return t; } Vector3f* position_flds() // Reference-getter { return &m_position; } this() { m_position = new Vector3f; } } void main() { Node n = new Node; writefln("A %s %s", n.position.x, n.position.y); n.position_flds.x = 1; n.position_flds.y = 2.2; writefln("B %s %s", n.position.x, n.position.y); Vector3f v = n.position; writefln("C %s %s", v.x, v.y); v.x = 10; v.y = 9.9; writefln("D %s %s", v.x, v.y); writefln("E %s %s", n.position.x, n.position.y); } /////////////////// -- Derek (skype: derek.j.parnell) Melbourne, Australia "Justice for David Hicks!" 17/04/2007 5:30:04 PM
Apr 17 2007
Reply to swiftcoder - Tristam MacDonald,I am fairly new to D, from a C++ background, and I am having a hard time coming up with a sensible way to deal with what is a fairly trivial example in C++:[...]Vector3f v = n.position();If I'm reading you correctly, then the problem is that in this line you want value semantics and are getting references semantics. One solution would be to make Vector3f a struct and have .position return a pointer to it. In D, pointers to structs and structs are almost identical from a syntax standpoint (no . vs ->) Then when you want value semantics you would use *n.position().
Apr 17 2007
Maybe you want to take a look at this thread which describes a fairly similar (if not the same) problem: http://www.digitalmars.com/d/archives/digitalmars/D/Problem_with_Point_property_49990.html Henning -- v4sw7Yhw4ln0pr7Ock2/3ma7uLw5Xm0l6/7DGKi2e6t6ELNSTVXb7AHIMOen5a2Xs5Mr2g5ACPR hackerkey.com
Apr 17 2007