www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why does this opCmp function not work

reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
So, here we have an opCmp function for a class named shape. It 
compares the .volume of each shape:

  int opCmp(shape rhs)
{
     int exp;
     if(this.volume == rhs.volume)
         exp =  0;
     else if(this.volume > rhs.volume)
         exp =  1;
     else if(this.volume < rhs.volume)
         exp = -1;
     return exp;

}

here is how I would use it:
shape test = new shape(pos);/*Ignore the constructor argument 
it's not relevant here*/
shape test1 = new shape(pos); //same variable
writeln(test == test1);
writeln(test.opCmp(test1) == 0);

Both .volume are the same, but the output says this:

false
true

note that the documentation for comparing classes with an opCmp 
function defined is said to be this: x.opCmp(y) op 0

can anybody explain this to me?
Sep 23 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Wednesday, 23 September 2020 at 10:37:09 UTC, Ruby The 
Roobster wrote:
 So, here we have an opCmp function for a class named shape. It 
 compares the .volume of each shape:

  int opCmp(shape rhs)
 {
     int exp;
     if(this.volume == rhs.volume)
         exp =  0;
     else if(this.volume > rhs.volume)
         exp =  1;
     else if(this.volume < rhs.volume)
         exp = -1;
     return exp;

 }

 here is how I would use it:
 shape test = new shape(pos);/*Ignore the constructor argument 
 it's not relevant here*/
 shape test1 = new shape(pos); //same variable
 writeln(test == test1);
 writeln(test.opCmp(test1) == 0);

 Both .volume are the same, but the output says this:

 false
 true

 note that the documentation for comparing classes with an opCmp 
 function defined is said to be this: x.opCmp(y) op 0

 can anybody explain this to me?
Equality is defined by opEquals. Which for classes defaults to pointer identity comparison.
Sep 23 2020
parent reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Wednesday, 23 September 2020 at 10:38:42 UTC, Stefan Koch 
wrote:
 Equality is defined by opEquals.
 Which for classes defaults to pointer identity comparison.
Using opEquals, it still returns false. Does this have something to do with volume being a property?: int volume() property { //... } note that this returns true: test.opEquals(test1) but not this: test == test1 here is the function: bool opEquals(shape rhs) { return(rhs.volume == this.volume); } despite the fact that x == y should be the same as x.opEquals(y), calling opEquals directly returns true, but otherwise it returns false also, compiler complains if I don't have this alias: alias opEquals = Object.opEquals. that might have something to do with it.
Sep 23 2020
parent reply Simen =?UTF-8?B?S2rDpnLDpXM=?= <simen.kjaras gmail.com> writes:
On Wednesday, 23 September 2020 at 11:19:15 UTC, Ruby The 
Roobster wrote:
 bool opEquals(shape rhs)
 {
 return(rhs.volume == this.volume);
 }
This is a wrong implementation of opEquals for a class. The documentation mentions (https://dlang.org/spec/operatoroverloading.html#equals):
 4. If overridding Object.opEquals() for classes, the class 
 member function signature should look like:
 
 class C
 {
     override bool opEquals(Object o) { ... }
 }
A correct implementation would be: override bool opEquals(Object o) { if (!cast(Shape)o) return false; return (cast(Shape)o).volume == this.volume; } -- Simen
Sep 23 2020
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/23/20 7:28 AM, Simen Kjærås wrote:
 On Wednesday, 23 September 2020 at 11:19:15 UTC, Ruby The Roobster wrote:
 bool opEquals(shape rhs)
 {
 return(rhs.volume == this.volume);
 }
This is a wrong implementation of opEquals for a class. The documentation mentions (https://dlang.org/spec/operatoroverloading.html#equals):
 4. If overridding Object.opEquals() for classes, the class member 
 function signature should look like:

 class C
 {
     override bool opEquals(Object o) { ... }
 }
A correct implementation would be: override bool opEquals(Object o) {     if (!cast(Shape)o) return false;     return (cast(Shape)o).volume == this.volume; }
Or, more D way: if(auto other = cast(Shape)o) return other.volume == this.volume; return false; -Steve
Sep 23 2020
prev sibling parent Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Wednesday, 23 September 2020 at 11:28:11 UTC, Simen Kjærås 
wrote:
 A correct implementation would be:

 override bool opEquals(Object o) {
     if (!cast(Shape)o) return false;
     return (cast(Shape)o).volume == this.volume;
 }

 --
   Simen
Thanks. This solved the problem.
Sep 23 2020