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