www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - My story of C++ vs. D and trying to return classes by value

reply Michael Coupland <mcoupland hmc.edu> writes:
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 19 2004
parent reply Norbert Nemec <Norbert.Nemec gmx.de> writes:
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
parent reply Michael Coupland <mcoupland hmc.edu> writes:
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
parent Andy Friesen <andy ikagames.com> writes:
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
May 20 2004