Hi!
While implementing and overloading several different operators for my
structure I've got stuck with an error.
As noticed in the attachment, in my opBinaryRight function I mimic the
opBinary (left) operator by instantiating the structure itself to avoid
implementing duplicates of the binary operator overloads.
The opBinaryRight operator is defined as following:
DVector2 opBinaryRight(string op, T)(T lhs) if(Accepts!T)
{
// Error: template instance vector.DVector2.__ctor!(DVector2) error
instantiating
return DVector2(lhs).opBinary!op(this);
}
I create an additional DVector2 structure and then calls the opBinary
operator. When creating this DVector2 structure the following
constructor gets called:
this(T)(T arg) if(Accepts!T)
{
static if(isScalar!T)
this(arg, arg);
else
// Error: constructor call must be in a constructor
this(arg.tupleof);
}
As one can clearly see, the constructor call is within a constructor.
Now my questions are; is this a bug with DMD or is it something with my
code example and is there any workarounds/solutions?
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)
}