Bug 7864 – Structs with class members can't be sorted
Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-04-08T17:15:00Z
Last change time
2015-06-09T01:31:20Z
Assigned to
nobody
Creator
issues.dlang
Comments
Comment #0 by issues.dlang — 2012-04-08T17:15:12Z
This compiles with 2.058, but not with the latest head (which I assume is the same as 2.059 beta)
import std.algorithm;
import std.string;
class C
{
string str;
this(string str)
{
this.str = str;
}
override int opCmp(Object o) const
{
auto rhs = cast(C)o;
assert(rhs);
return cmp(str, rhs.str);
}
}
struct S
{
C c;
this(C c)
{
this.c = c;
}
int opCmp(S rhs) const
{
if(c < rhs.c)
return -1;
if(c > rhs.c)
return 1;
return 0;
}
int opCmp(const ref S rhs) const
{
if(c < rhs.c)
return -1;
if(c > rhs.c)
return 1;
return 0;
}
}
void main()
{
S[] stuff;
sort(stuff);
}
/home/jmdavis/dmd2/linux/bin/../../src/phobos/std/algorithm.d(6802): Error: static assert "Invalid predicate passed to sort: a < b"
q.d(52): instantiated from here: sort!("a < b",cast(SwapStrategy)0,S[])
The same occurs if you use a SysTime instead of C, so the problem occurs whether the class is directly or indirectly insed of S. This strikes me as being similar to issue# 7808 (though not identical). That was fixed however, and this isn't.
Comment #1 by k.hara.pg — 2012-04-08T19:17:46Z
(In reply to comment #0)
> This compiles with 2.058, but not with the latest head (which I assume is the
> same as 2.059 beta)
>
[snip]
>
> /home/jmdavis/dmd2/linux/bin/../../src/phobos/std/algorithm.d(6802): Error:
> static assert "Invalid predicate passed to sort: a < b"
> q.d(52): instantiated from here: sort!("a < b",cast(SwapStrategy)0,S[])
This is wrong opCmp overload problem, not compiler regression.
If you change opCmp signatures to:
int opCmp(const S rhs) const
int opCmp(const ref S rhs) const
// may work in general
or:
int opCmp(const S rhs) const
// may work in general if S allows lvalue copying
or:
int opCmp(S rhs) const
// In this case, sorted elements is always mutable so it works
or:
int opCmp(const ref S rhs) const
// In this case, current std.algorithm.sort implementation only requires
// lvalue comparison, so it works)
Then you can compile it.
> The same occurs if you use a SysTime instead of C, so the problem occurs
> whether the class is directly or indirectly insed of S. This strikes me as
> being similar to issue# 7808 (though not identical). That was fixed however,
> and this isn't.
Bug 7808 was alias this type resolution problem. There is no matter.
Comment #2 by bearophile_hugs — 2012-04-09T10:42:47Z
(In reply to comment #1)
> If you change opCmp signatures to:
>
> int opCmp(const S rhs) const
> int opCmp(const ref S rhs) const
> // may work in general
Maybe one opCmp is enough in general:
struct S {
C c;
int opCmp()(const auto ref S rhs) const {
if (c < rhs.c) return -1;
if (c > rhs.c) return 1;
return 0;
}
}