Returning a struct by reference

grauzone none at example.net
Sat Mar 21 08:04:26 PDT 2009


Simon TRENY wrote:
> Daniel Keep Wrote:
> 
>>
>> 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
> 
> Here is a complete example of what I'd like to achieve:
> struct Position {
>    private float m_x;
>    private float m_y;
> 
>    public float x() {
>       return m_x;
>    }
> 
>    public void x(float x) {
>       m_x = x;
>       EmitSignal("changed");
>    }
> 
>    public float y() {
>       return m_y;
>    }
> 
>    public void y(float y) {
>       m_y = y;
>       EmitSignal("changed");
>    }
> }
> 
> class Object {
>    private Position m_position;
> 
>    public this() {
>       m_position.CallOnSignal("changed", onPositionChanged);
>    }
> 
>    //This syntax is not working
>    public ref Position position() {
>       return m_position;
>    }
> 
>    public void onPositionChanged() {
>       writeln("Position Changed!!);
>    }
> }
> 
> With this "fictional" code, I could write things like:
> object.position.x = 14; and the object will be "aware" that its position has changed.
> 
> Making the "position"-variable public will lead the user to be able to do things like this:
> object.position = pos2; and then, the object won't be "aware" that its position has changed. And this is a problem for me.

But if position is returned as ref, this still could happen. The 
returned value is still assignable, and because it's a ref, overwriting 
it is like overwriting m_position directly. As far as I see, your 
position()-getter just emulates a public field. Including overwriting by 
assignment.


Now D2.0 has const. If position() would return a const object, this kind 
of unwanted "overwriting" couldn't happen. This improves correctness, 
because uncatched changes or changes to temporaries can't happen. But 
then again, the setters in the Position struct wouldn't work, because 
the struct is const (as far as I understand the const system). This 
means returning the field as a "const ref" wouldn't help.


Also, how is this EmitSignal() working? What happens if you write:

Position p = object.position;
p.x = 14; //EmitSignal() calls what?

p is simply a bit-copy of the struct returned by the getter, and 
EmitSignal() has no way to check if it's still supposed to notify class 
Object. (All solutions I can come up with sound really hairy and hackish.)

Maybe you're better off with Position as a class instead of a struct. 
Even when you use D2.0's const/opAssign/copy-ctor/post-blit/ref-return 
features.

Looking forward to the replies pointing out that D2.0 actually allows to 
implement exactly what you want, and how this is done.

> I hope it's clearer now



More information about the Digitalmars-d mailing list