www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Anybody have any idea on how to do shared operator overloads?

reply Ruby The Roobster <rubytheroobster yandex.com> writes:
A stripped down version of some code I have:

```d
public import std.complex;

public interface Mtype
{
     // ...
}

public class Number : Mtype
{
     public:
         this(Complex!real num = Complex!real(0,0))
         {
             this.num = num;
         }
         this(shared Complex!real num = cast(shared 
Complex!real)Complex!real(0,0))
         {
             this.num.re = num.re;
             this.im.re = im.re;
         }
         Number opBinary(string op)(Number rhs) //Standard opBinary
         {
             mixin("return new Number(this.num " ~ op ~ " 
rhs.num);");
         }
         shared(Number) opBinary(string op)(shared Number rhs) 
shared
         {
             return new shared Number(); //Placeholder untill I 
can get the code to work
         }
     package:
         Complex!real num;
}

bool isMtype(T)()
{
     bool ret = true;
     // ...
     shared T p = new shared T();
     shared T p2 = new shared T();
     ret &= __traits(compiles, T, p + p2);
     return ret;
}

static assert(isMtype!Number); //This fails.
```

Upon adding the line shared T c = p + p2 to isMtype,  I get the 
following error:



source\dutils\math\core.d(138,22): Error: function call through 
null class reference `null`
source\dutils\math\core.d(142,15):        called from here: 
`isMtype()`
source\dutils\math\core.d(142,1):        while evaluating: 
`static assert(cast(int)isMtype() == 1)`

Anybody know how to get a working shared operator overload and 
fix this mess?
Jun 01 2022
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 6/1/22 17:36, Ruby The Roobster wrote:
 A stripped down version of some code I have:
Not much experience here but I made two changes: 1) Added 'shared':
          this(Complex!real num = Complex!real(0,0)) shared
          {
              this.num = num;
          }
          this(shared Complex!real num = cast(shared
 Complex!real)Complex!real(0,0))
          {
              this.num.re = num.re;
              this.im.re = im.re;
2) Fixed apparent typos: this.num.im = num.im;
          }
I can't guarantee that correct functions are called. It just compiles with 2.100.0. :) Ali
Jun 01 2022
parent reply Ruby The Roobster <rubytheroobster yandex.com> writes:
On Thursday, 2 June 2022 at 01:00:57 UTC, Ali Çehreli wrote:
 On 6/1/22 17:36, Ruby The Roobster wrote:
 A stripped down version of some code I have:
Not much experience here but I made two changes: 1) Added 'shared':
          this(Complex!real num = Complex!real(0,0)) shared
          {
              this.num = num;
          }
          this(shared Complex!real num = cast(shared
 Complex!real)Complex!real(0,0))
          {
              this.num.re = num.re;
              this.im.re = im.re;
2) Fixed apparent typos: this.num.im = num.im;
          }
I can't guarantee that correct functions are called. It just compiles with 2.100.0. :) Ali
Yes, those were typos. However, when making this post, I forgot to mark ```this(shared Complex!real num = cast(shared Complex!real)Complex!real(0,0))``` as shared. The other constructor is not marked as shared in my code, considering as shared classes have all of their members marked as shared.
Jun 01 2022
parent reply Ruby The Roobster <rubytheroobster yandex.com> writes:
On Thursday, 2 June 2022 at 01:29:39 UTC, Ruby The Roobster wrote:
 On Thursday, 2 June 2022 at 01:00:57 UTC, Ali Çehreli wrote:
 On 6/1/22 17:36, Ruby The Roobster wrote:
 A stripped down version of some code I have:
Not much experience here but I made two changes: 1) Added 'shared':
          this(Complex!real num = Complex!real(0,0)) shared
          {
              this.num = num;
          }
          this(shared Complex!real num = cast(shared
 Complex!real)Complex!real(0,0))
          {
              this.num.re = num.re;
              this.im.re = im.re;
2) Fixed apparent typos: this.num.im = num.im;
          }
I can't guarantee that correct functions are called. It just compiles with 2.100.0. :) Ali
Yes, those were typos. However, when making this post, I forgot to mark ```this(shared Complex!real num = cast(shared Complex!real)Complex!real(0,0))``` as shared. The other constructor is not marked as shared in my code, considering as shared classes have all of their members marked as shared. I also have a bug: __traits(compiles) only checks if the expressions are SEMANTICALLY correct, not if they actually compile, which they don't. Interestingly, this code compiles between 2.063 and 2.066.1, if you were to put it into run.dlang.io, given the above changes (including the p1 + p2!), and set to all compilers.
Jun 01 2022
parent Tejas <notrealemail gmail.com> writes:
On Thursday, 2 June 2022 at 01:49:32 UTC, Ruby The Roobster wrote:
 On Thursday, 2 June 2022 at 01:29:39 UTC, Ruby The Roobster 
 wrote:
 On Thursday, 2 June 2022 at 01:00:57 UTC, Ali Çehreli wrote:
 On 6/1/22 17:36, Ruby The Roobster wrote:
 A stripped down version of some code I have:
Not much experience here but I made two changes: 1) Added 'shared':
          this(Complex!real num = Complex!real(0,0)) shared
          {
              this.num = num;
          }
          this(shared Complex!real num = cast(shared
 Complex!real)Complex!real(0,0))
          {
              this.num.re = num.re;
              this.im.re = im.re;
2) Fixed apparent typos: this.num.im = num.im;
          }
I can't guarantee that correct functions are called. It just compiles with 2.100.0. :) Ali
Yes, those were typos. However, when making this post, I forgot to mark ```this(shared Complex!real num = cast(shared Complex!real)Complex!real(0,0))``` as shared. The other constructor is not marked as shared in my code, considering as shared classes have all of their members marked as shared. I also have a bug: __traits(compiles) only checks if the expressions are SEMANTICALLY correct, not if they actually compile, which they don't. Interestingly, this code compiles between 2.063 and 2.066.1, if you were to put it into run.dlang.io, given the above changes (including the p1 + p2!), and set to all compilers.
I fixed the typos and added some extra constructors and also wrote a little more complex `opBinary` for the `shared` overload of `Number`. Now the thing works(AFAICT): ```d public import std.complex; public import std.stdio; public interface Mtype { // ... } public class Number : Mtype { public: // new code begin this() { this.num = Complex!real(1,1); } this() shared { this.num = Complex!real(1,1); } // new code ends this(Complex!real num = Complex!real(0,0)) { this.num = num; } this(shared Complex!real num = cast(shared Complex!real)Complex!real(0,0)) shared { this.num.re = num.re; this.num.im = num.im; } Number opBinary(string op)(Number rhs) //Standard opBinary { mixin("return new Number(this.num " ~ op ~ " rhs.num);"); } shared(Number) opBinary(string op)(shared Number rhs) shared //changed this code a little as well { mixin(q{return new shared Number(Complex!real(this.num.re} ~ op ~ q{rhs.num.re, this.num.im} ~ op ~ q{rhs.num.im));}); //Placeholder untill I can get the code to work } package: Complex!real num; } bool isMtype(T)() { bool ret = true; // ... shared T p = new shared T(); shared T p2 = new shared T(); ret &= __traits(compiles, T, p + p2); return ret; } static assert(isMtype!Number); //This fails. Not anymore :D void main() { shared num1 = new shared Number(); shared num2 = new shared Number(); auto num3 = num1 + num2; writeln("real: ", num3.num.re, "\nimaginary: ",num3.num.im); } ```
Jun 01 2022