Thread overview
Why does this opCmp function not work
Sep 23, 2020
Ruby The Roobster
Sep 23, 2020
Stefan Koch
Sep 23, 2020
Ruby The Roobster
Sep 23, 2020
Simen Kjærås
Sep 23, 2020
Ruby The Roobster
September 23, 2020
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?
September 23, 2020
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.
September 23, 2020
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.
September 23, 2020
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
September 23, 2020
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
September 23, 2020
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.