"inout return type" and "inout variable"

Regan Heath regan at netwin.co.nz
Sat Mar 18 03:51:48 PST 2006


On Sat, 18 Mar 2006 11:02:53 +0000 (UTC), Hong Wing  
<Hong_member at pathlink.com> wrote:
> Hi, yes! exactly that's the problem for me, I am writing a protein  
> modeling software and use vector and matrices heavily, and I start to  
> see things like:*result = (*v1) + (*v2) * (*v3)
>
> notice how all the * * * starts to make things very cluttered.

Yeah, I see the problem.

You could call the operator overloads directly, eg.
   result = v1.opAdd(v2.opMul(v3));

but that's almost as bad.

If you have opAdd(T *) and opMul(T *) then doesn't this work:
   *result = v1 + *v2 * v3;

I just tried it, and it seems to (example below).

However, isn't your bigger problem all the temporary structs being created  
and copied in the examples above?

eg. (*v2) * (*v3) produces a temporary struct, which is then added to  
(*v1) producing another temporary struct, which is then copied to *result.  
Can the compiler ever optimise any of those temporaries away?

Example:

*result = (*v1) + (*v2) * (*v3)

could be rewritten:

*result = *v3; //copy struct
*result *= v2; //opMulAssign(T *rhs)
*result += v1; //opAddAssign(T *rhs)

Here the opXAssign operators can access the rhs and add/mul them to/with  
result directly to avoid the temporary struct copy.

Example:

import std.string;
import std.stdio;

struct Foo
{
	int x;
	int y;
	int z;
	
	char[] toString() { return  
"("~std.string.toString(x)~","~std.string.toString(y)~","~std.string.toString(z)~")";  
}
	
	Foo opAdd(Foo rhs)
	{
		return opAdd(&rhs);
	}
	
	Foo opAdd(Foo* rhs)
	{
		Foo n;

		n.x = x+rhs.x;
		n.y = y+rhs.y;
		n.z = z+rhs.z;
		
		return n;
	}

	Foo opMul(Foo rhs)
	{
		return opAdd(&rhs);
	}

	Foo opMul(Foo* rhs)
	{
		Foo n;
		
		n.x = x*rhs.x;
		n.y = y*rhs.y;
		n.z = z*rhs.z;
		
		return n;
	}
	
	Foo* opAddAssign(Foo *rhs)
	{
		x += rhs.x;
		y += rhs.y;
		z += rhs.z;
		return this;
	}

	Foo* opMulAssign(Foo *rhs)
	{
		x *= rhs.x;
		y *= rhs.y;
		z *= rhs.z;
		return this;
	}
}

class Bar
{
private:
	Foo m_foo;
public:
	Foo* foo() { return &m_foo; }
	Foo* foo(Foo* value) { m_foo = *value; return foo(); }	
	Foo* foo(Foo value)  { m_foo = value;  return foo(); }
}

void main()
{
	Foo* a = new Foo();
	Bar b = new Bar();
	Bar c = new Bar();
	Bar d = new Bar();
	
	b.foo.x = 1;
	b.foo.y = 1;
	b.foo.z = 1;

	c.foo.x = 2;
	c.foo.y = 2;
	c.foo.z = 2;

	d.foo.x = 3;
	d.foo.y = 3;
	d.foo.z = 3;
		
	*a = b.foo + *c.foo * d.foo;
	
	writefln("%s",(*a).toString());
	
	*a = *d.foo;
	*a *= c.foo;
	*a += b.foo;
	
	writefln("%s",(*a).toString());
}

Regan



More information about the Digitalmars-d mailing list