Operator Overloading and boilerplate code

Timon Gehr timon.gehr at gmx.ch
Sat Jul 2 15:23:52 PDT 2011


Your example with reduced boilerplate code:



struct DVECTOR2 {
 template Accepts(T){enum Accepts=is(T==DVECTOR2) || is(T==float) ||
is(T==D3DXVECTOR2) || is(T==POINT);}
 template isScalar(T){enum isScalar=is(T==float);}
 float x = 0f, y=0f;

 this()(float x, float y) {
  this.x = x;
  this.y = y;
 }

 this()(float xy) { this(xy,xy); }

 // Implement D3DXVECTOR2 and POINT support
 this(T)(T arg) if(Accepts!T && !isScalar!T) {
  this.x = arg.x;
  this.y = arg.y;
 }

 DVECTOR2 opUnary(string op)() if(op == "-") { return DVECTOR2(-x, -y); }
 DVECTOR2 opBinary(string op,T)(T rhs) if(Accepts!T) {
  enum rx="rhs"~isScalar!T?"":".x", ry=isScalar!T?"":".y";
  return DVECTOR2(mixin("x" ~ op ~ "rhs"~rx), mixin("y" ~ op ~ "rhs"~ry));
 }
 DVECTOR2 opBinaryRight(string op,T)(T lhs) if(Accepts!T) { return
DVECTOR2(lhs).opBinary!op(this); }
 ref DVECTOR2 opAssign(T)(T rhs) if(Accepts!T) {
  static if(isScalar!T) x=y=rhs; else x=rhs.y, y=rhs.y; return this;
 }
 ref DVECTOR2 opOpAssign(string op,T)(T rhs) if(Accepts!T) {
return(this.opAssign(opBinary!op(rhs))); }
 T opCast(T)() if(Accepts!T && !isScalar!T) { return T(x, y); }
}

unittest
{
 DVECTOR2 test = DVECTOR2(2f, 2f);
 test += 2f;
 assert(test.x == 4f);
}

Should work.

Cheers,
-Timon


More information about the Digitalmars-d-learn mailing list