Weird opEquals Problem

H. S. Teoh hsteoh at quickfur.ath.cx
Wed Feb 22 18:32:22 PST 2012


On Wed, Feb 22, 2012 at 09:17:17PM -0500, Kevin Cox wrote:
> Oh, ok.
> 
> First of all the docs appear somewhat misleading.  I thought that function
> was an example on how to overload it.  That could be clarified a little.
> 
> Second of all, isn't that inefficient?  And  if you wanted to be able to
> compare to another type you don't control?  I think it would make more
> sense to have it pick the best match much like other overloads.

Well, that's only part of the story. :) The full story is that "a==b"
actually translates to something like this:

	if (a is b)
		return true;

	if (a is null && b !is null || a !is null && b is null)
		return false;

	if (typeof(a) == typeof(b))
		return a.opEquals(b);

	return a.opEquals(b) && b.opEquals(a);

So in the simple cases (one argument is null, or both objects are the
same type) only one call to opEquals is made. Only in the full general
case you get two calls.

As for comparing against a type you don't control, the best bet is to
write your own comparison function (named something other than
"opEquals"). For example:

	class A {
		bool compare(Object o) {
			// I like to be equal to everything
			return true;
		}
	}
	class B {
	}

	auto a = new A;
	auto b = new B;
	assert(a.compare(b));

The reason is that D guarantees that "==" is:

(1) reflexive (a==a for any a);
(2) symmetric (a==b if and only if b==a); and
(3) transitive (if a==b and b==c then a==c).

This allows the compiler to safely optimize expressions containing ==
comparisons without changing the code's semantics.

Allowing one-sided comparisons like you suggest would break symmetry
(a.opEquals(b) != b.opEquals(a)), and likely transitivity as well.


T

-- 
Chance favours the prepared mind. -- Louis Pasteur


More information about the Digitalmars-d-learn mailing list