www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - opEquals default behaviour - poorly documented or am I missing

reply MichaelZ <michael.zinn funkwerk-itk.com> writes:
In http://dlang.org/operatoroverloading.html#eqcmp it is stated 
that

"If opEquals is not specified, the compiler provides a default 
version that does member-wise comparison."

However, doesn't this only apply to structs, and not objects?  
The default behaviour of opEquals for objects seems to be "is".


A few paragraphs later, in 
http://dlang.org/operatoroverloading.html#compare, the 
description of the default version is repeated:
""
If overriding Object.opCmp() for classes, the class member 
function signature should look like:
...
If structs declare an opCmp member function, it should have the 
following form:
...
Note that opCmp is only used for the inequality operators; 
expressions like a == b always uses opEquals. **If opCmp is 
defined but opEquals isn't, the compiler will supply a default 
version of opEquals that performs member-wise comparison.**
""

Even here, the fact that the described default opEquals behaviour 
appears to only apply to structs is far from clear.


Or am I missing something that should be obvious?

Thanks,
-- MichaelZ
Nov 17 2015
parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 11/17/2015 12:40 AM, MichaelZ wrote:
 In http://dlang.org/operatoroverloading.html#eqcmp it is stated that

 "If opEquals is not specified, the compiler provides a default version
 that does member-wise comparison."

 However, doesn't this only apply to structs, and not objects?
Correct. The behavior for class objects is the following algorithm on the same page: http://dlang.org/operatoroverloading.html#equals This one: bool opEquals(Object a, Object b) { if (a is b) return true; if (a is null || b is null) return false; if (typeid(a) == typeid(b)) return a.opEquals(b); return a.opEquals(b) && b.opEquals(a); } Ali
Nov 17 2015
next sibling parent reply user123ABCabc <user123ABCabc aAbBcC.br> writes:
On Tuesday, 17 November 2015 at 19:44:36 UTC, Ali Çehreli wrote:
     if (typeid(a) == typeid(b)) return a.opEquals(b);
Wow this is terrible to compare two objects in D. The line I quoted means that two TypeInfoClass are likely to be allocated, right ? But usually when comparing objects one rather cares about the reference itself, so a comparison of the two heap addresses is enough in this case. (meaning same or not same instance, regardless of the their members values).
Nov 17 2015
next sibling parent Steven Schveighoffer <schveiguy yahoo.com> writes:
On 11/17/15 3:25 PM, user123ABCabc wrote:
 On Tuesday, 17 November 2015 at 19:44:36 UTC, Ali Çehreli wrote:
     if (typeid(a) == typeid(b)) return a.opEquals(b);
Wow this is terrible to compare two objects in D. The line I quoted means that two TypeInfoClass are likely to be allocated, right ?
No, those are immutable stored in the data segment. Fetching them costs only doing the fetch of the class info pointer. -Steve
Nov 17 2015
prev sibling parent Jonathan M Davis via Digitalmars-d-learn writes:
On Tuesday, November 17, 2015 20:25:30 user123ABCabc via Digitalmars-d-learn
wrote:
 On Tuesday, 17 November 2015 at 19:44:36 UTC, Ali Çehreli wrote:
     if (typeid(a) == typeid(b)) return a.opEquals(b);
Wow this is terrible to compare two objects in D. The line I quoted means that two TypeInfoClass are likely to be allocated, right ?
No. As Steven points out. No allocation takes place.
 But usually when comparing objects one rather cares about the
 reference itself, so a comparison of the two heap addresses is
 enough in this case. (meaning same or not same instance,
 regardless of the their members values).
Really? I would have expected caring about reference equality to be the _rare_ case rather than the common one. And if that's what you want, == isn't the right operator to use anyway. That's what the is operator is for. Regardless, as the code posted by Ali indicates, the free function opEquals that gets called by == for classes does check whether they're the same object first by using the is operator, so all of the other checking is only done if they're not the same object. - Jonathan M Davis
Nov 19 2015
prev sibling parent MichaelZ <michael.zinn funkwerk-itk.com> writes:
On Tuesday, 17 November 2015 at 19:44:36 UTC, Ali Çehreli wrote:
 On 11/17/2015 12:40 AM, MichaelZ wrote:
 In http://dlang.org/operatoroverloading.html#eqcmp it is
stated that
 "If opEquals is not specified, the compiler provides a
default version
 that does member-wise comparison."

 However, doesn't this only apply to structs, and not objects?
Correct. The behavior for class objects is the following algorithm on the same page: http://dlang.org/operatoroverloading.html#equals This one: bool opEquals(Object a, Object b) { if (a is b) return true; if (a is null || b is null) return false; if (typeid(a) == typeid(b)) return a.opEquals(b); return a.opEquals(b) && b.opEquals(a); }
Sure, but that defers to the a.opEquals / b.opEquals in many the interesting cases :) Which comes back to the original point: that I feel the documentation I quoted is at least easily misunderstood, if not straight out wrong.
Nov 18 2015