digitalmars.D.bugs - Array .sort property doesn't play nicely with overloaded opCmp
- Jarrett Billingsley (40/40) Jul 15 2005 Look at the following code:
- John Demme (17/71) Jul 15 2005 I complained about this awhile ago. The problem is actually much more
- Brad Beveridge (5/81) Jul 15 2005 Though I can see why this was once a problem, now that D has templates
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.
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








Brad Beveridge <brad somewhere.net>