Custom opCmp for struct array sort
Steven Schveighoffer
schveiguy at yahoo.com
Mon Dec 1 07:56:21 PST 2008
"New" wrote
> Hello,
>
> I am new with D and am stuck with something I hope somebody can help me
> with it.
> I am trying sort an array of paths which can take the two following forms:
>
> /usr ---> normal path
> /bin=/other/bin ---> a symlink
>
> When I sort these paths, in the case of symlinks I want to ignore the
> right hand side and I just use the path before the "=" sign.
>
> The array docs for DMD 2.0, say that can create a structure and create a
> opCmp function to cutomise the way sort works. I have tried this but
> calling .sort does not seem to pick-up my custom opCmp.
>
> Any help would be very appreciated. I am including the code below
>
> Thanks a lot
> --------------------------------------------------------------------
>
> struct Path {
> invariant(char) [] thePath;
>
> int opCmp(Path p) {
> int pos;
> invariant(char) [] a;
> invariant(char) [] b;
> if( (pos=find(this.thePath, RegExp("="))) > -1 ) {
> a = this.thePath[0 .. pos];
> } else {
> a = this.thePath;
> }
> if( (pos=find(p.thePath, RegExp("="))) > -1 ) {
> b = p.thePath[0 .. pos];
> } else {
> b = p.thePath;
> }
> int cosa = std.string.cmp(a, b);
> writefln( a, " comp ", b, "=", cosa);
> return std.string.cmp(a, b);
> }
> }
>
> int main(char[][] args) {
> char[][][Path] contents;
>
> Path one;
> one.thePath = "/002=/other_dir";
> contents[one] = cast(char[][])["aa","bb","cc","dd"];
>
> Path two;
> two.thePath = "/001";
> contents[two] = cast(char[][])["aa","bb","cc","dd"];
>
> foreach(item; contents.keys.sort) {
> writefln( item.thePath );
> }
>
> return 0;
> }
The problem is the opCmp function signature.
One of the undocumented (as far as I know) features of the compiler is that
for a struct, if there is an opCmp of a certain signature, the compiler
saves a function pointer to that opCmp in that struct's typeinfo as 'the'
opCmp to use when comparing two of those structs. This is used in
associative arrays and with sort.
the appropriate signature for D2 (as of 2.019) is:
struct S
{
int opCmp(const S *s) const;
}
So in order for your code to be used during sort in D 2, you need to change
your signature to:
> int opCmp(const Path * p) const {
Then it should work. If it's different in D 2.021 (and it probably should
be given the advent of 'SafeD' requiring no pointers), then I don't know
what it might be, but I'd guess you'd replace 'const Path *p' with 'ref
const Path p'.
I think these 'special' features should be documented, probably in the
operators page. I'll file a bugzilla request.
-Steve
More information about the Digitalmars-d
mailing list