www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Passing rvalues to functions expecting const ref

reply "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
Hi. In C++, I can do this:

struct Vector3
{
   Vector3(_x, _y, _z); // constructor
};

float dot(const Vector3 &v, const Vector3 &u);

dot(Vector3(0, 0, 0), Vector3(1, 1, 1));
------------------------------------

In D, I can't -- and it's really annoying, because I am forced to 
make a copy, i.e:
dot(Vector3 v, Vector3 u);

I don't want this.

The other solution is this:
Vector3 v = {0, 0, 0};
Vector3 u = {1, 1, 1};

dot(v,u); // dot(const ref Vector3 v, const ref Vector3 u);

But it's not as clean.
Why can't I do what I can in C++? Is it a technical or a design 
decision? Are there plans to support it?
Dec 23 2012
parent reply "Namespace" <rswhite4 googlemail.com> writes:
As long as you use structs this should work, as you can see here: 
http://dpaste.dzfl.pl/03adf3d1
But if you use classes, it does not work anymore. So I like it a 
lot, that it works with structs. :)
Dec 23 2012
next sibling parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Sunday, 23 December 2012 at 12:08:47 UTC, Namespace wrote:
 As long as you use structs this should work, as you can see 
 here: http://dpaste.dzfl.pl/03adf3d1
 But if you use classes, it does not work anymore. So I like it 
 a lot, that it works with structs. :)
Thank you. I had forgotten to supply the constructor to the struct :/
Dec 23 2012
prev sibling next sibling parent reply "John Chapman" <johnch_atms hotmail.com> writes:
On Sunday, 23 December 2012 at 12:08:47 UTC, Namespace wrote:
 As long as you use structs this should work, as you can see 
 here: http://dpaste.dzfl.pl/03adf3d1
 But if you use classes, it does not work anymore. So I like it 
 a lot, that it works with structs. :)
I don't think this will work after 2.061 is released. The behaviour is changing to disallow struct literals as lvalues.
Dec 23 2012
parent reply "Namespace" <rswhite4 googlemail.com> writes:
On Sunday, 23 December 2012 at 18:32:47 UTC, John Chapman wrote:
 On Sunday, 23 December 2012 at 12:08:47 UTC, Namespace wrote:
 As long as you use structs this should work, as you can see 
 here: http://dpaste.dzfl.pl/03adf3d1
 But if you use classes, it does not work anymore. So I like it 
 a lot, that it works with structs. :)
I don't think this will work after 2.061 is released. The behaviour is changing to disallow struct literals as lvalues.
I hope not. As long as "auto ref" don't work for normal functions, this change would be very inconvenient... Minas Mina: Show me the whole code, I think that your opBinary functions returns rvalues. This would be a good and important case for "auto ref". But until now it is only for template paramters...
Dec 23 2012
parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
On Sunday, 23 December 2012 at 20:40:09 UTC, Namespace wrote:
 Minas Mina:
 Show me the whole code, I think that your opBinary functions 
 returns rvalues.
 This would be a good and important case for "auto ref". But 
 until now it is only for template paramters...
struct Vector3 { float x, y, z; this(float _x, float _y, float _z) { x = _x; y = _y; z = _z; } // negate operator Vector3 opUnary(string s)() const if( s == "-" ) { Vector3 temp = this; temp.x = -temp.x; temp.y = -temp.y; temp.z = -temp.z; return temp; } // + operator for completeness Vector3 opUnary(string s)() const if( s == "+" ) { return this; } // binary operators Vector3 opBinary(string op) (float val) const { static if( op == "+" ) { Vector3 temp = this; temp.x += val; temp.y += val; temp.z += val; } else static if( op == "-" ) { Vector3 temp = this; temp.x -= val; temp.y -= val; temp.z -= val; } else static if( op == "*" ) { Vector3 temp = this; temp.x *= val; temp.y *= val; temp.z *= val; } else static if( op == "/" ) { Vector3 temp = this; temp.x /= val; temp.y /= val; temp.z /= val; } return temp; } Vector3 opBinary(string op) (Vector3 v) const { static if( op == "+" ) { Vector3 temp = this; temp.x += v.x; temp.y += v.y; temp.z += v.z; } static if( op == "-" ) { Vector3 temp = this; temp.x -= v.x; temp.y -= v.y; temp.z -= v.z; } static if( op == "*" ) { Vector3 temp = this; temp.x *= v.x; temp.y *= v.y; temp.z *= v.z; } return temp; } } /// dot product of two Vector3 vectors safe pure float dot(Vector3 u, Vector3 v) { return u.x * v.x + u.y * v.y + u.z * v.z; } dot is making copies now because what I have shown earlier does not work... It's what I'm using now.
Dec 23 2012
prev sibling parent "Minas Mina" <minas_mina1990 hotmail.co.uk> writes:
There's another problem though:

struct Vector3
{
	float x, y, z;
	
	this(float _x, float _y, float _z)
	{
		x = _x;
		y = _y;
		z = _z;
	}
	
	// the binary +, - operators are defined
}

Vector3 cross(const ref Vector3 a, const ref Vector3 b);
...

Vector3 n = cross(b-a, c-a);


raytracing/triangle.d(58): Error: function 
raytracing.vector.cross (ref const(Vector3) a, ref const(Vector3) 
b) is not callable using argument types (Vector3,Vector3)
raytracing/triangle.d(58): Error: this.b.opBinary(this.a) is not 
an lvalue
raytracing/triangle.d(58): Error: this.c.opBinary(this.a) is not 
an lvalue

That's what I actually want.
Dec 23 2012