Thread overview
Array .sort property doesn't play nicely with overloaded opCmp
Jul 15, 2005
John Demme
Jul 15, 2005
Brad Beveridge
July 15, 2005
Look at the following code:

import std.stdio;
import std.random;

class A
{
 this(int a)
 {
  x=a;
 }

 int x;

 int opCmp(A other)
 {
  return x-other.x;
 }
}

void main()
{
 A[] a=new A[10];
 foreach(uint i, inout A ai; a)
 {
  ai=new A(rand() % 10);
  writefln(ai.x);
 }

 a.sort;

 writefln();

 foreach(A ai; a)
 {
  writefln(ai.x);
 }
}

The problem is that a[] is not sorted.  But change the opCmp() to this:

int opCmp(Object o)
{
 A other=cast(A)o;
 return x-other.x;
}

And it works fine.

The array .sort property is only looking for opCmp(Object) overloads; it doesn't like any other parameter type.  This is inconsistent with the behavior of the comparison operators, which do use the overloaded opCmps.


July 15, 2005
I complained about this awhile ago.  The problem is actually much more generic than with arrays.  Any class A which overloads Object's opCmp, and uses a more specific parameter, say a class A (this class is your class A) doesn't actually overload it.  That is, if you're looking at A as an object, not an A, it'll never call A.opCmp.  The reason this affects arrays, is because all class arrays are effectively cast into Objects- you'd have to look into the array sources in Phobos to determine exactly why this is.

I see this as a big issue, but not one that's too hard to get around.
Add the follow to A:
int opCmp(Object o) {
	A a = cast(A)o;
	if (a !is null)
		return opCmp(a);
	assert(false);
}

On Fri, 2005-07-15 at 14:30 -0400, Jarrett Billingsley wrote:
> Look at the following code:
> 
> import std.stdio;
> import std.random;
> 
> class A
> {
>  this(int a)
>  {
>   x=a;
>  }
> 
>  int x;
> 
>  int opCmp(A other)
>  {
>   return x-other.x;
>  }
> }
> 
> void main()
> {
>  A[] a=new A[10];
>  foreach(uint i, inout A ai; a)
>  {
>   ai=new A(rand() % 10);
>   writefln(ai.x);
>  }
> 
>  a.sort;
> 
>  writefln();
> 
>  foreach(A ai; a)
>  {
>   writefln(ai.x);
>  }
> }
> 
> The problem is that a[] is not sorted.  But change the opCmp() to this:
> 
> int opCmp(Object o)
> {
>  A other=cast(A)o;
>  return x-other.x;
> }
> 
> And it works fine.
> 
> The array .sort property is only looking for opCmp(Object) overloads; it doesn't like any other parameter type.  This is inconsistent with the behavior of the comparison operators, which do use the overloaded opCmps.
> 
> 

July 15, 2005
John Demme wrote:
> I complained about this awhile ago.  The problem is actually much more
> generic than with arrays.  Any class A which overloads Object's opCmp,
> and uses a more specific parameter, say a class A (this class is your
> class A) doesn't actually overload it.  That is, if you're looking at A
> as an object, not an A, it'll never call A.opCmp.  The reason this
> affects arrays, is because all class arrays are effectively cast into
> Objects- you'd have to look into the array sources in Phobos to
> determine exactly why this is.
> 
> I see this as a big issue, but not one that's too hard to get around.
> Add the follow to A:
> int opCmp(Object o) {
> 	A a = cast(A)o;
> 	if (a !is null)
> 		return opCmp(a);
> 	assert(false);
> }
> 
> On Fri, 2005-07-15 at 14:30 -0400, Jarrett Billingsley wrote:
> 
>>Look at the following code:
>>
>>import std.stdio;
>>import std.random;
>>
>>class A
>>{
>> this(int a)
>> {
>>  x=a;
>> }
>>
>> int x;
>>
>> int opCmp(A other)
>> {
>>  return x-other.x;
>> }
>>}
>>
>>void main()
>>{
>> A[] a=new A[10];
>> foreach(uint i, inout A ai; a)
>> {
>>  ai=new A(rand() % 10);
>>  writefln(ai.x);
>> }
>>
>> a.sort;
>>
>> writefln();
>>
>> foreach(A ai; a)
>> {
>>  writefln(ai.x);
>> }
>>}
>>
>>The problem is that a[] is not sorted.  But change the opCmp() to this:
>>
>>int opCmp(Object o)
>>{
>> A other=cast(A)o;
>> return x-other.x;
>>}
>>
>>And it works fine.
>>
>>The array .sort property is only looking for opCmp(Object) overloads; it doesn't like any other parameter type.  This is inconsistent with the behavior of the comparison operators, which do use the overloaded opCmps. 
>>
>>
> 
> 
Though I can see why this was once a problem, now that D has templates can't this be corrected internally to use correctly typed arrays inside Phobos?

Brad