import win32.directx.d3dx9 : D3DXVECTOR2; import win32.windows : POINT; struct DVector2 { // Controls that the argument is one of the following types: float, DVector2, D3DXVECTOR2, POINT template Accepts(T) { enum Accepts = is(T == DVector2) || is(T == float) || is(T == D3DXVECTOR2) || is(T == POINT); } // Whether the argument is a float or not template isScalar(T) { enum isScalar = is(T == float); } // X and Y Axis float x = 0f, y = 0f; // Default Constructor this()(float x, float y) { this.x = x; this.y = y; } // Implement D3DXVECTOR2 and POINT support this(T)(T arg) if(Accepts!T) { static if(isScalar!T) this(arg, arg); else this(arg.tupleof); // Error: constructor call must be in a constructor } // Binary Operations DVector2 opBinary(string op, T)(T rhs) if(Accepts!T) { enum rx = isScalar!T ? "" : ".x"; enum ry = isScalar!T ? "" : ".y"; return DVector2(mixin("x" ~ op ~ "rhs" ~ rx), mixin("y" ~ op ~ "rhs" ~ ry)); } // Right Binary Operator DVector2 opBinaryRight(string op, T)(T lhs) if(Accepts!T) { return DVector2(lhs).opBinary!op(this); // Error: template instance vector.DVector2.__ctor!(DVector2) error instantiating } // Assign Operator ref DVector2 opAssign(T)(T rhs) if(Accepts!T) { static if(isScalar!T) x = y = rhs; else { x = rhs.x; y = rhs.y; } return this; } } void main(string[] args) { DVector2 test = DVector2(0f, 1f); // This statement leads to the following errors: // (L28) Error: constructor call must be in a constructor // (L43) Error: template instance vector.DVector2.__ctor!(DVector2) error instantiating // (L70) Error: instantiated from here: opBinaryRight!("+", DVector2) test = test + DVector2(2f, 1f); // Error: instantiated from here: opBinaryRight!("+", DVector2) }