www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Returning a struct by reference

reply Simon TRENY <simon.treny free.fr> writes:
Hi there!

I'm quite new at D and I'm still just playing with it, but there is a thing
that I find currently missing. Sometimes, I'd like to be able to return a
struct by reference and not by value. For example, in the following example:

struct Position {
   float x;
   float y;
}

class Object {
   private Position m_position;

   public Position position() {
      return m_position;
   }
}

I'd like to be able to write things like this: myObject.position.x = 43 to
actually change the position of the object. But right now, since "position" is
a struct, it is returned by value and not by reference, and then the previous
instruction won't change the position of the object, but it will work on a copy
of the position field.


Here is the solutions that I can see to this problem:

- Returning a pointer to the position: "public Position *position() { ... }",
but I'd like to keep my code as free from pointers as possible.
 - Make "Position" a class and not a struct. That could be a solution, but
then, when I'll do things like "Position pos = object.position; pos.x = 43;",
it will effectively change the position of the object, which I wouldn't like
with this syntax.

Actually, I'd like to be able to do a thing like this:
   public ref Position position() {
      return m_position;
   }
which would be the equivalent form to passing structs by reference in a
parameter.

Is there a way to do this in D?

Regards,
Simon
Mar 21 2009
parent reply grauzone <none example.net> writes:
Simon TRENY wrote:
 Hi there!
 
 I'm quite new at D and I'm still just playing with it, but there is a thing
that I find currently missing. Sometimes, I'd like to be able to return a
struct by reference and not by value. For example, in the following example:
 
 struct Position {
    float x;
    float y;
 }
 
 class Object {
    private Position m_position;
 
    public Position position() {
       return m_position;
    }
 }
 
 I'd like to be able to write things like this: myObject.position.x = 43 to
actually change the position of the object. But right now, since "position" is
a struct, it is returned by value and not by reference, and then the previous
instruction won't change the position of the object, but it will work on a copy
of the position field.
 
 
 Here is the solutions that I can see to this problem:
 
 - Returning a pointer to the position: "public Position *position() { ... }",
but I'd like to keep my code as free from pointers as possible.
  - Make "Position" a class and not a struct. That could be a solution, but
then, when I'll do things like "Position pos = object.position; pos.x = 43;",
it will effectively change the position of the object, which I wouldn't like
with this syntax.
 
 Actually, I'd like to be able to do a thing like this:
    public ref Position position() {
       return m_position;
    }
 which would be the equivalent form to passing structs by reference in a
parameter.
 
 Is there a way to do this in D?

Yes. Make the variable public. class Object { Position position; } This code is even simpler than your's above. Incredible, isn't it?
 Regards,
 Simon
 

Mar 21 2009
parent reply Simon TRENY <simon.treny free.fr> writes:
grauzone Wrote:

 Simon TRENY wrote:
 Hi there!
 
 I'm quite new at D and I'm still just playing with it, but there is a thing
that I find currently missing. Sometimes, I'd like to be able to return a
struct by reference and not by value. For example, in the following example:
 
 struct Position {
    float x;
    float y;
 }
 
 class Object {
    private Position m_position;
 
    public Position position() {
       return m_position;
    }
 }
 
 I'd like to be able to write things like this: myObject.position.x = 43 to
actually change the position of the object. But right now, since "position" is
a struct, it is returned by value and not by reference, and then the previous
instruction won't change the position of the object, but it will work on a copy
of the position field.
 
 
 Here is the solutions that I can see to this problem:
 
 - Returning a pointer to the position: "public Position *position() { ... }",
but I'd like to keep my code as free from pointers as possible.
  - Make "Position" a class and not a struct. That could be a solution, but
then, when I'll do things like "Position pos = object.position; pos.x = 43;",
it will effectively change the position of the object, which I wouldn't like
with this syntax.
 
 Actually, I'd like to be able to do a thing like this:
    public ref Position position() {
       return m_position;
    }
 which would be the equivalent form to passing structs by reference in a
parameter.
 
 Is there a way to do this in D?

Yes. Make the variable public. class Object { Position position; } This code is even simpler than your's above. Incredible, isn't it?

Ok, but then, what if I'd like to make the variable "read-only"? i.e. preventing the user from writing things like this: myObject.position = pos2;
 
 Regards,
 Simon
 


Mar 21 2009
next sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Simon TRENY wrote:
 Ok, but then, what if I'd like to make the variable "read-only"? i.e.
preventing the user from writing things like this:
 myObject.position = pos2;
 

So... you're rejecting a solution on the basis that it prevents you from doing the exact opposite of what you want to do? *boggle* -- Daniel
Mar 21 2009
prev sibling parent reply grauzone <none example.net> writes:
Simon TRENY wrote:
 grauzone Wrote:
 
 Simon TRENY wrote:
 Hi there!

 I'm quite new at D and I'm still just playing with it, but there is a thing
that I find currently missing. Sometimes, I'd like to be able to return a
struct by reference and not by value. For example, in the following example:

 struct Position {
    float x;
    float y;
 }

 class Object {
    private Position m_position;

    public Position position() {
       return m_position;
    }
 }

 I'd like to be able to write things like this: myObject.position.x = 43 to
actually change the position of the object. But right now, since "position" is
a struct, it is returned by value and not by reference, and then the previous
instruction won't change the position of the object, but it will work on a copy
of the position field.


 Here is the solutions that I can see to this problem:

 - Returning a pointer to the position: "public Position *position() { ... }",
but I'd like to keep my code as free from pointers as possible.
  - Make "Position" a class and not a struct. That could be a solution, but
then, when I'll do things like "Position pos = object.position; pos.x = 43;",
it will effectively change the position of the object, which I wouldn't like
with this syntax.

 Actually, I'd like to be able to do a thing like this:
    public ref Position position() {
       return m_position;
    }
 which would be the equivalent form to passing structs by reference in a
parameter.

 Is there a way to do this in D?

class Object { Position position; } This code is even simpler than your's above. Incredible, isn't it?

Ok, but then, what if I'd like to make the variable "read-only"? i.e. preventing the user from writing things like this: myObject.position = pos2;

Then you write a getter that simply returns the field by value. The D compiler will (hopefully) inline the getter function, so there shouldn't be a disadvantage in performance. Note: I think D2.0 wants to introduce ref-returns at some point in the future.
 Regards,
 Simon



Mar 21 2009
parent reply Simon TRENY <simon.treny free.fr> writes:
grauzone Wrote:

 Simon TRENY wrote:
 grauzone Wrote:
 
 Simon TRENY wrote:
 Hi there!

 I'm quite new at D and I'm still just playing with it, but there is a thing
that I find currently missing. Sometimes, I'd like to be able to return a
struct by reference and not by value. For example, in the following example:

 struct Position {
    float x;
    float y;
 }

 class Object {
    private Position m_position;

    public Position position() {
       return m_position;
    }
 }

 I'd like to be able to write things like this: myObject.position.x = 43 to
actually change the position of the object. But right now, since "position" is
a struct, it is returned by value and not by reference, and then the previous
instruction won't change the position of the object, but it will work on a copy
of the position field.


 Here is the solutions that I can see to this problem:

 - Returning a pointer to the position: "public Position *position() { ... }",
but I'd like to keep my code as free from pointers as possible.
  - Make "Position" a class and not a struct. That could be a solution, but
then, when I'll do things like "Position pos = object.position; pos.x = 43;",
it will effectively change the position of the object, which I wouldn't like
with this syntax.

 Actually, I'd like to be able to do a thing like this:
    public ref Position position() {
       return m_position;
    }
 which would be the equivalent form to passing structs by reference in a
parameter.

 Is there a way to do this in D?

class Object { Position position; } This code is even simpler than your's above. Incredible, isn't it?

Ok, but then, what if I'd like to make the variable "read-only"? i.e. preventing the user from writing things like this: myObject.position = pos2;

Then you write a getter that simply returns the field by value. The D compiler will (hopefully) inline the getter function, so there shouldn't be a disadvantage in performance.

If I add a getter-property that returns the field by value, the following instruction "object.position.x = 12;" won't modify the position of the object, but will only modify the returned copy of the position, right? That's actually why I'd like to have a getter that returns the field by reference and not by value.
 
 Note: I think D2.0 wants to introduce ref-returns at some point in the 
 future.
 
 Regards,
 Simon




Mar 21 2009
parent BCS <none anon.com> writes:
Hello Simon,

 If I add a getter-property that returns the field by value, the
 following instruction "object.position.x = 12;" won't modify the
 position of the object, but will only modify the returned copy of the
 position, right?
 
 That's actually why I'd like to have a getter that returns the field
 by reference and not by value.
 

That is correct. Reference returns are on the todo list. For now this Hack should work. struct S { float x; float y; } class C { S s class C_S { void x(float v){ s.x=v; } void y(float v){ s.y=v; } } C_S pos() { return new C_S(); } }
Mar 21 2009