Operator Overloading and boilerplate code

Loopback elliott.darfink at gmail.com
Sat Jul 2 08:31:38 PDT 2011


Hi!

I've made a two dimensional vector structure (x, y) which is very
primitive, the only real thing that I want to do with this structure
is support for nearly all operators and support for D3DXVECTOR2 and
POINT structures.

While writing this structure the boilerplate code has steadily
increased. Since I am new to D I mainly wanted to ask if there are any
solutions to prevent this amount of boilerplate code with mixins etc...

The unittest, also, fail to compile. When I am trying to use the
in-place assignment operator the compiler complains saying this;

Error: function dx.directx.DVECTOR2.opAssign (ref const const(DVECTOR2) 
rhs) is not callable using argument types (DVECTOR2)
Error: cannot implicitly convert expression (this.opBinary(rhs)) of type 
DVECTOR2 to float
Error: template instance dx.directx.DVECTOR2.opOpAssign!("+") error 
instantiating

The first two errors origins from the last opOpAssign operator (taking
a float argument) whilst the last error is from the "test += 2f"
statement.

struct DVECTOR2
{
	float x = 0f;
	float y = 0f;
	
	this(float x, float y)
	{
		this.x = x;
		this.y = y;
	}
	
	this(float xy)
	{
		this.x = xy;
		this.y = xy;
	}
	
	// Implement D3DXVECTOR2 support
	this(const ref D3DXVECTOR2 vec)
	{
		this.x = vec.x;
		this.y = vec.y;
	}
	
	// Implement POINT support
	this(const ref POINT pnt)
	{
		this.x = pnt.x;
		this.y = pnt.y;
	}
	
	// Return a inverse vector
	DVECTOR2 opUnary(string op)() if(op == "-") { return DVECTOR2(-x, -y); }
	
	// The Binary Operators
	DVECTOR2 opBinary(string op)(DVECTOR2 rhs) { return DVECTOR2(mixin("x" 
~ op ~ "rhs.x"), mixin("y" ~ op ~ "rhs.y")); }
	DVECTOR2 opBinary(string op)(D3DXVECTOR2 rhs) { return 
opBinary!op(DVECTOR2(rhs)); }
	DVECTOR2 opBinary(string op)(POINT rhs) { return 
opBinary!op(DVECTOR2(rhs)); }
	DVECTOR2 opBinary(string op)(float rhs) { return 
opBinary!op(DVECTOR2(rhs)); }
	
	// Right Operators Support
	DVECTOR2 opBinaryRight(string op)(DVECTOR2 lhs) { return 
lhs.opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(D3DXVECTOR2 lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(POINT lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }
	DVECTOR2 opBinaryRight(string op)(float lhs) { return 
DVECTOR2(lhs).opBinary!op(this); }
	
	// Assignment Operator
	ref DVECTOR2 opAssign(const ref DVECTOR2 rhs) { x = rhs.x; y = rhs.y; 
return this; }
	ref DVECTOR2 opAssign(const ref D3DXVECTOR2 rhs) { return 
(this.opAssign(DVECTOR2(rhs))); }
	ref DVECTOR2 opAssign(const ref POINT rhs) { return 
(this.opAssign(DVECTOR2(rhs))); }
	ref DVECTOR2 opAssign(float rhs) { return (this.opAssign(DVECTOR2(rhs))); }

	// In-Place Assignment Operators
	ref DVECTOR2 opOpAssign(string op)(DVECTOR2 rhs) { return 
(this.opAssign(opBinary!op(rhs))); }
	ref DVECTOR2 opOpAssign(string op)(D3DXVECTOR2 rhs) { return 
(this.opAssign(opBinary!op(rhs))); }
	ref DVECTOR2 opOpAssign(string op)(POINT rhs) { return 
(this.opAssign(opBinary!op(rhs))); }

	// This is where the two first errors occur
	ref DVECTOR2 opOpAssign(string op)(float rhs) { return 
(this.opAssign(opBinary!op(rhs))); }
	
	// Operator Casts
	D3DXVECTOR2 opCast(T)() if(is(T == D3DXVECTOR2)) { return 
D3DXVECTOR2(x, y); }
	POINT opCast(T)() if(is(T == POINT)) { return POINT(cast(int) x, 
cast(int) y); }
}

unittest
{
	DVECTOR2 test = DVECTOR2(2f, 2f);
	test += 2f; // This is where the last error occurs
	
	assert(test.x == 4f);
}


More information about the Digitalmars-d-learn mailing list