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. 


can't this be corrected internally to use correctly typed arrays inside Phobos? Brad
Jul 15 2005