digitalmars.D.bugs - Array .sort property doesn't play nicely with overloaded opCmp
- "Jarrett Billingsley" <kb3ctd2 yahoo.com> Jul 15 2005
- John Demme <me teqdruid.com> Jul 15 2005
- Brad Beveridge <brad somewhere.net> Jul 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.
Jul 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.
Jul 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.
can't this be corrected internally to use correctly typed arrays inside Phobos? Brad
Jul 15 2005








Brad Beveridge <brad somewhere.net>