Thread overview
My story of C++ vs. D and trying to return classes by value
May 20, 2004
Michael Coupland
May 20, 2004
Norbert Nemec
May 20, 2004
Michael Coupland
May 20, 2004
Andy Friesen
May 20, 2004
So I was porting my C++ vector code to D in preparation for my first big D project, and I ran into the following problem: I have overloaded * and *= scalar multiplication operations for the vector class, and I would prefer to write *= in terms of *. However, I tried copying my C++ code, which resulted in the following (broken) D code:

// BROKEN
class Vec2( ScalarType )
{
	// ... code ...
	
	////////////////////////////////////
	// Overloaded * and *=
	Vec2 opMul( ScalarType s )
	{
		return new Vec2( x*s, y*s );	
	}
	
	Vec2 opMulAssign( ScalarType s )
	{
		this = this * s;
		return this;
	}
}

I tried compiling, and *= didn't seem to be working. In retrospect, it was a silly coding error: I'm overwriting the this pointer in opMulAssign(), which was resulting in some of that good ol' "undefined" behavior. As I was typing up a complaint/help request to this board, I realized that there was an interesting solution: do it the other way! So I wrote * in terms of *= and got the following (working) code:

// WORKS!
class Vec2( ScalarType )
{
	// ... code ...

	////////////////////////////////////
	// Overloaded * and *=
	Vec2 opMul( ScalarType s )
	{
		Vec2 res = new Vec2(this);
		res *= s;
		return res;
	}
	
	Vec2 opMulAssign( ScalarType s )
	{
		x *= s;
		y *= s;
		return this;
	}
}

It just goes to show that you need to be careful when you're used to C++. I'm still trying to get my D-legs under me, and I figured that this might be a helpful story for others who are still beginning with D.

	Michael Coupland
May 20, 2004
You would probably want to use struct instead of class. A struct is always handled by value.




Michael Coupland wrote:

> So I was porting my C++ vector code to D in preparation for my first big D project, and I ran into the following problem: I have overloaded * and *= scalar multiplication operations for the vector class, and I would prefer to write *= in terms of *. However, I tried copying my C++ code, which resulted in the following (broken) D code:
> 
> // BROKEN
> class Vec2( ScalarType )
> {
> // ... code ...
> 
> ////////////////////////////////////
> // Overloaded * and *=
> Vec2 opMul( ScalarType s )
> {
> return new Vec2( x*s, y*s );
> }
> 
> Vec2 opMulAssign( ScalarType s )
> {
> this = this * s;
> return this;
> }
> }
> 
> I tried compiling, and *= didn't seem to be working. In retrospect, it was a silly coding error: I'm overwriting the this pointer in opMulAssign(), which was resulting in some of that good ol' "undefined" behavior. As I was typing up a complaint/help request to this board, I realized that there was an interesting solution: do it the other way! So I wrote * in terms of *= and got the following (working) code:
> 
> // WORKS!
> class Vec2( ScalarType )
> {
> // ... code ...
> 
> ////////////////////////////////////
> // Overloaded * and *=
> Vec2 opMul( ScalarType s )
> {
> Vec2 res = new Vec2(this);
> res *= s;
> return res;
> }
> 
> Vec2 opMulAssign( ScalarType s )
> {
> x *= s;
> y *= s;
> return this;
> }
> }
> 
> It just goes to show that you need to be careful when you're used to C++. I'm still trying to get my D-legs under me, and I figured that this might be a helpful story for others who are still beginning with D.
> 
> Michael Coupland

May 20, 2004
Norbert Nemec wrote:

> You would probably want to use struct instead of class. A struct is always
> handled by value.

I thought about doing that, but I was a little hesitant because I wouldn't be able to have:

	this( ScalarType s )
	{
		x = s;
		y = s;
	}

But in retrospect, using a struct is a 'more correct' choice (vectors are simple aggregates). I don't particularly use that constructor anyway, but I'd appreciate a suggestion on how to recreate the following (C++)

	typedef Vec2<float> Vec2f;
	Vec2f test_vec( 1, 2 );

I don't know how to do something like this without constructors similar to the one above. I know that /static/ structs can be initialized as:

	static Vec2f test_vec = { 1, 2 };

which would be fine for me, except that it doesn't work for non-static variables. Any suggestions?

	Michael Coupland
May 20, 2004
Michael Coupland wrote:

> I'd appreciate a suggestion on how to recreate the following (C++)
> 
>     typedef Vec2<float> Vec2f;
>     Vec2f test_vec( 1, 2 );
> 
> I don't know how to do something like this without constructors similar to the one above. I know that /static/ structs can be initialized as:
> 
>     static Vec2f test_vec = { 1, 2 };
> 
> which would be fine for me, except that it doesn't work for non-static variables. Any suggestions?

You can come close by defining a static opCall method that returns a Vector to get this:

     Vector v = Vector(1,2,3);

I think it's ugly and evil, but you could also make a nonstatic opCall that makes the vector mutate and return itself:

     Vector v; v(1,2,3);

 -- andy