Mixin Templates and Operators

Tejas notrealemail at gmail.com
Wed Apr 6 16:36:51 UTC 2022


On Wednesday, 6 April 2022 at 10:36:04 UTC, francesco.andreetto 
wrote:
> I have two structs, point and vec, in which I want to implement 
> some arithmetic operations.
> The operations are:
>
> ```
> point - point = vec
> point + vec = point
> ```
>
> Using mixin templates the code compiles but calling the 
> operations in the main causes an "incompatible type" Error:
>
> ```d
> mixin template sum(T, R) {
>    R opBinary(string op)(T rhs) const
>    if (op == "+"){
>       return R(x + rhs.x, y + rhs.y, z + rhs.z);
>    }
> }
>
> mixin template diff(T, R) {
>    R opBinary(string op)(T rhs) const
>    if (op == "-") {
>       return R(x - rhs.x, y - rhs.y, z - rhs.z);
>    }
> }
>
> struct point{
>    float x, y, z;
>    mixin diff!(point, vec);
>    mixin sum!(vec, point);
> }
>
> struct vec{
>    float x, y, z;
> }
>
> void main(){
>    point p1 = {1,2,3}, p2 = {5,6,7};
>    vec v1 = p1-p2;
>
>    vec v2 = {2,-1,0};
>    point p3 = p1+v2;
> }
> ```
> The output of `dub run` is
>
> ```
> Performing "debug" build using /usr/bin/dmd for x86_64.
> query ~master: building configuration "application"...
> source/app.d(27,13): Error: incompatible types for `(p1) - 
> (p2)`: both operands are of type `point`
> source/app.d(30,15): Error: incompatible types for `(p1) + 
> (v2)`: `point` and `vec`
> /usr/bin/dmd failed with exit code 1.
> ```
>
> I tried to implement a single template:
>
> ```d
> mixin template sumDiff(T, R){
>    R opBinary(string op)(T rhs) const
>    if (op == "+" || op == "-"){
>       return mixin("R(x " ~ op ~ " rhs.x, y " ~ op ~ "rhs.y, z 
> " ~ op ~ " rhs.z)");
>    }
> }
> ```
>
> but the same error occurs.
>
> If I don't use the mixin templates and, instead, I overload the 
> operations into the structures everything works.
>
> ```d
> struct point{
>    float x, y, z;
>
>    vec opBinary(string op)(point rhs) const
>    if (op == "-") {
>       return vec(x - rhs.x, y - rhs.y, z - rhs.z);
>    }
>
>    point opBinary(string op)(vec rhs) const
>    if (op == "+") {
>       return point(x + rhs.x, y + rhs.y, z + rhs.z);
>    }
> }
>
> struct vec{
>    float x, y, z;
> }
>
> void main(){
>    point p1 = {1,2,3}, p2 = {5,6,7};
>    vec v1 = p1-p2;
>
>    vec v2 = {2,-1,0};
>    point p3 = p1+v2;
> }
> ```
>
> Am I doing something wrong or it is impossible to use mixin 
> templates like that?

Looks like a compiler bug, since substituting the real methods 
makes the `mixin template` code compile fine

Also, remove the `const`, otherwise the method will word only on 
`const` instances even if the bug gets fixed

```d
mixin template sum(T, R) {
    R opBinary(string op)(T rhs) const
    if (op == "+"){
       return R(x + rhs.x, y + rhs.y, z + rhs.z);
    }
}

mixin template diff(T, R) {
    R opBinary(string op)(T rhs) const
    if (op == "-") {
       return R(x - rhs.x, y - rhs.y, z - rhs.z);
    }
}

struct point{
    float x, y, z;
    mixin diff!(point, vec);
    mixin sum!(vec, point);
}

struct vec{
    float x, y, z;
}

void main(){
    point p1 = {1,2,3}, p2 = {5,6,7};
    vec v1 = p1.opBinary!"-"(p2);   // made - explicit

    vec v2 = {2,-1,0};
    point p3 = p1.opBinary!"+"(v2);  // made + explicit
}


More information about the Digitalmars-d-learn mailing list