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