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)
}

Reply via email to