templating opEquals/opCmp (e.g. for DSL/expression templates)

Dominikus Dittes Scherkl dominikus at scherkl.de
Wed Feb 13 20:49:49 UTC 2019


On Wednesday, 13 February 2019 at 18:42:43 UTC, H. S. Teoh wrote:
> On Wed, Feb 13, 2019 at 01:50:21AM +0000, Nicholas Wilson via 
> Digitalmars-d wrote:
>> On Wednesday, 13 February 2019 at 00:56:48 UTC, H. S. Teoh 
>> wrote:
>> > Frankly, I think it's a very good thing that in D comparison 
>> > operators are confined to opEquals/opCmp.
>> 
>> So do I. Many more objects have partial ordering than 
>> arithmetic, having opCmp under opBinary would be annoying.
>
> Actually, contrary to what Andrei has claimed in the past, 
> opCmp (as currently implemented) does NOT allow for a 
> consistent definition of a partial ordering.  I know because 
> I've tried to do it with an integer set type.  The problem is 
> that when opCmp returns 0, it's ambiguous whether it means 
> "incomparable" or "equal".  This makes it impossible to make <= 
> equivalent to the is-subset predicate. For example, here's a 
> prospective implementation:
>
> 	struct IntSet {
> 		Impl impl;
> 		int opCmp(in IntSet b) {
> 			bool isSubset = impl.isSubsetOf(b.impl);
> 			bool isSuperset = b.impl.isSubsetOf(impl);
>
> 			if (isSubset && isSuperset)
> 				return 0;
> 			else if (isSubset)
> 				return -1;
> 			else if (isSuperset)
> 				return 1;
> 			else
> 				return 0; // incomparable
> 		}

opCmp is allowed to return float, making it possible to 
distinguish all 4 possible values
float opCmp(in IntSet b) {
    bool isSubset = impl.isSubsetOf(b.impl);
    bool isSuperset = b.impl.isSubsetOf(impl);

    if (isSubset && isSuperset)
       return 0;
    else if (isSubset)
       return -1;
    else if (isSuperset)
       return 1;
    else
       return float.init; // incomparable - NaN
}

This works fine, I've used it in several types in my libraries.



More information about the Digitalmars-d mailing list