Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
April 17, 2007 re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
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)? |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to swiftcoder - Tristam MacDonald | 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/ |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | > 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/ |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to swiftcoder - Tristam MacDonald | 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 |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | 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
|
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to swiftcoder - Tristam MacDonald | 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(). |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to swiftcoder | 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
>
|
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to swiftcoder - Tristam MacDonald | 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 |
April 17, 2007 Re: re-creating C++'s reference bahavior | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | 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.
>
|
Copyright © 1999-2021 by the D Language Foundation