www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - Array .sort property doesn't play nicely with overloaded opCmp

reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
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. 
Jul 15 2005
parent reply John Demme <me teqdruid.com> writes:
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. 
 
 
Jul 15 2005
parent Brad Beveridge <brad somewhere.net> writes:
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
Jul 15 2005