www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - mixin template bug with opBinary?

reply Anthony Quizon <anthoq88 gmail.com> writes:
Hello,

I'm trying to create a mixin for quick binary operator overloads 
by passing in types with a corresponding associative array of 
strings to functions. However,
the code I currently have:

```
module foo;

mixin template opBi(
     A, A function(A, A)[string] f0,
) {
     static foreach (k, f; f0) { A opBinary(string op: k)(A r) { 
return f(this, r); } }
}

struct A {
     mixin opBi!(
         A, [ "+": (A a, A b) => a],
     );
}

struct B {
     mixin opBi!(
         B, [ "+": (B a, B b) => a],
     );
}


```

Will not let me override operators on both struct A and B.

I get:
```
foo.d(16): Error: mixin `foo.B.opBi!(B, ["+":function (B a, B b) 
pure nothrow  nogc  safe => a])` does not match template 
declaration `opBi(A, A function(A, A)[string] f0)`
```

Is this a bug or am I doing something wrong?
Jul 22 2022
next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Friday, 22 July 2022 at 12:33:37 UTC, Anthony Quizon wrote:
 Is this a bug or am I doing something wrong?
I think this is a bug. The compiler must not take well to this pattern, maybe the assoc array template argument, but idk. It looks like the first type used gets cached and reused even if it is supposed to change. I vaguely recall seeing this before.... but yeah smells buggy anyway. An alternative you might consider is dropping some of the type and using typeof(this): ``` module foo; mixin template opBi( alias f0 ) { static foreach (k, f; f0) { typeof(this) opBinary(string op: k)(typeof(this) r) { return f(this, r); } } } struct A { mixin opBi!( [ "+": (A a, A b) => a], ); } struct B { mixin opBi!( [ "+": (B a, B b) => a], ); } ``` That sidesteps the bug though it just trusts you pass the right type to `f0`.
Jul 22 2022
parent Anthony Quizon <anthoq88 gmail.com> writes:
On Friday, 22 July 2022 at 12:56:44 UTC, Adam D Ruppe wrote:
 ```
 mixin template opBi(
     alias f0
 ) {
     static foreach (k, f; f0) { typeof(this) opBinary(string op:
     k)(typeof(this) r) { return f(this, r); } }
 }
 ```
Thanks, this seems to do the trick.
Jul 22 2022
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 7/22/22 8:33 AM, Anthony Quizon wrote:
 Hello,
 
 I'm trying to create a mixin for quick binary operator overloads by 
 passing in types with a corresponding associative array of strings to 
 functions. However,
 the code I currently have:
 
 ```
 module foo;
 
 mixin template opBi(
      A, A function(A, A)[string] f0,
 ) {
      static foreach (k, f; f0) { A opBinary(string op: k)(A r) { return 
 f(this, r); } }
 }
 
 struct A {
      mixin opBi!(
          A, [ "+": (A a, A b) => a],
      );
 }
 
 struct B {
      mixin opBi!(
          B, [ "+": (B a, B b) => a],
      );
 }
 
 
 ```
 
 Will not let me override operators on both struct A and B.
 
 I get:
 ```
 foo.d(16): Error: mixin `foo.B.opBi!(B, ["+":function (B a, B b) pure 
 nothrow  nogc  safe => a])` does not match template declaration `opBi(A, 
 A function(A, A)[string] f0)`
 ```
 
 Is this a bug or am I doing something wrong?
It's typing the AA differently, and therefore it doesn't fit. The type of the AA you are passing in is `T1[string]`, where it's expecting `T2[string]`, where: `T1` is `B function(B, B) pure nothrow nogc safe` `T2` is `B function(B, B)` I don't know if there's a better way to do this, other than use a further template parameter to match the function type passed in. -Steve
Jul 22 2022
prev sibling parent Paul Backus <snarwin gmail.com> writes:
On Friday, 22 July 2022 at 12:33:37 UTC, Anthony Quizon wrote:
 I get:
 ```
 foo.d(16): Error: mixin `foo.B.opBi!(B, ["+":function (B a, B 
 b) pure nothrow  nogc  safe => a])` does not match template 
 declaration `opBi(A, A function(A, A)[string] f0)`
 ```

 Is this a bug or am I doing something wrong?
Looks like this bug: https://issues.dlang.org/show_bug.cgi?id=22540
Jul 22 2022