Thread overview
opEquals for multiple types
Jul 08, 2012
Wouter Verhelst
Jul 08, 2012
Jonathan M Davis
Jul 09, 2012
Wouter Verhelst
July 08, 2012
Hi,

I'm trying to implement opEquals. I had originally done something like

class foo : bar {
      bool opEquals(bar e) {
           ... code here ...
      }
      bool opEquals(foo e) {
           ... somewhat more specialized code here ...
      }
}

(where bar is an interface)

but that gave me a message about how hiding Object.opEquals is deprecated.

My next attempt was to add a

      bool opEquals(Object o)

which would then decide which opEquals function to call based on what typeid() on the Object returns. But since I want to have a version involving an interface, that's not going to fly.

What's the best way forward?

-- 
The volume of a pizza of thickness a and radius z can be described by the following formula:

pi zz a
July 08, 2012
On Sunday, July 08, 2012 10:56:25 Wouter Verhelst wrote:
> Hi,
> 
> I'm trying to implement opEquals. I had originally done something like
> 
> class foo : bar {
>       bool opEquals(bar e) {
>            ... code here ...
>       }
>       bool opEquals(foo e) {
>            ... somewhat more specialized code here ...
>       }
> }
> 
> (where bar is an interface)
> 
> but that gave me a message about how hiding Object.opEquals is deprecated.
> 
> My next attempt was to add a
> 
>       bool opEquals(Object o)
> 
> which would then decide which opEquals function to call based on what typeid() on the Object returns. But since I want to have a version involving an interface, that's not going to fly.
> 
> What's the best way forward?

For classes, opEquals _must_ take Object. It can't take anything else. If you want to do something differently for specific base classes, you're going to need to deal with it within opEquals via casting. However, that's _still_ not likely to do what you want, because D ensures that equality goes in _both_ directions, so if the types differ, opEquals must be true for both a.opEquals(b) and b.opEquals(a). You can't have only one side deciding that it's equal to the other. They have to agree.

- Jonathan M Davis
July 09, 2012
Jonathan M Davis <jmdavisProg@gmx.com> writes:

> On Sunday, July 08, 2012 10:56:25 Wouter Verhelst wrote:
>> Hi,
>> 
>> I'm trying to implement opEquals. I had originally done something like
>> 
>> class foo : bar {
>>       bool opEquals(bar e) {
>>            ... code here ...
>>       }
>>       bool opEquals(foo e) {
>>            ... somewhat more specialized code here ...
>>       }
>> }
>> 
>> (where bar is an interface)
>> 
>> but that gave me a message about how hiding Object.opEquals is deprecated.
>> 
>> My next attempt was to add a
>> 
>>       bool opEquals(Object o)
>> 
>> which would then decide which opEquals function to call based on what typeid() on the Object returns. But since I want to have a version involving an interface, that's not going to fly.
>> 
>> What's the best way forward?
>
> For classes, opEquals _must_ take Object. It can't take anything else.

Ah. Well, that explains that.

> If you want to do something differently for specific base classes, you're going to need to deal with it within opEquals via casting. However, that's _still_ not likely to do what you want, because D ensures that equality goes in _both_ directions, so if the types differ, opEquals must be true for both a.opEquals(b) and b.opEquals(a). You can't have only one side deciding that it's equal to the other. They have to agree.

Right.

Having thought about it some more, I've come to the conclusion that opEquals is probably not what I need.

I have a class NodeTemplate that defines a number of properties that a particular node in my data structure needs to conform to. It need not fully specify each and every property of the node (that's why it's called a "template"), but it does need to match on the properties that are specified. The NodeTemplate class has a private member of type TypeInfo, and knows how to instantiate an object given some context and the properties it knows about.

Since it's not a full description, "equality" is probably not a good concept to apply to this particular comparison. As such, I've implemented it as a "matches()" function, which takes an argument of the interface shared by these objects, and can do some inflection etc to see if the object would be okay according to this template.

That works, and it's probably cleaner too.

Never the less, thanks for your explanations; it did clarify things a bit.

-- 
The volume of a pizza of thickness a and radius z can be described by the following formula:

pi zz a