RedBlackTree and myClass

tsbockman via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sun Jan 3 06:49:59 PST 2016


On Sunday, 3 January 2016 at 10:55:05 UTC, AntonSotov wrote:
> import std.container.rbtree;
>
> class myClass {
>     string str;
> }
>
>
> int main()
> {
>     auto tree = new RedBlackTree!myClass;
>     return 0;
> }
>
>
> Error: mutable method object.Object.opCmp is not callable using 
> a inout object
> Error: template instance std.functional.binaryFun!("a < b", 
> "a", "b").binaryFun!(inout(myClass), myClass) error 
> instantiating
> /////////////////////////////////////////
>
> How to use RedBlackTree of the objects of of its class?

Internally, `RedBlackTree` needs to be able to compare two 
instances of your class. It cannot do so because you haven't 
implemented the comparison operators:
     http://dlang.org/spec/operatoroverloading.html#eqcmp

It's trying to use the default Object.opCmp() method, but can't 
because it doesn't accept constant inputs (`inout` is one of the 
many ways to mark something as constant in D: 
http://dlang.org/spec/const3.html). You wouldn't want it to use 
the default method anyway, since it doesn't understand the 
meaning of your class's data fields.

class myClass {
     string str;

     override string toString() const {
         return "{myClass: " ~ str ~ "}"; }

     override size_t toHash() const {
         return hashOf(str); }

     override bool opEquals(Object that) const {
         return opEquals(cast(myClass) that); }
     bool opEquals(const myClass that) const {
         return this.str == that.str; }

     int opCmp(const myClass that) const {
         if(this.str < that.str)
             return -1; // less than
         if(this.str > that.str)
             return  1; // greater than

         return 0; // equal
     }
}

Note that all of the new methods are marked `const` on the right. 
This is to indicate that they do not mutate (change the value of) 
`this` instance when they are called. Similarly, the `const` in 
`const myClass that` is a promise by the method not to modify 
`that`.

This use of `const` is required to make `RedBlackTree` work, 
because it is apparently marking things as `inout` somewhere. 
Constant values (of whatever sort) cannot be passed to a function 
unless that function promises not to modify them.

It won't compile without the `toString()` either, because 
somewhere inside it wants to generate a `string` representation 
of a `myClass` instance, probably as part of an exception message.

`toHash()` is not required to make your trivial example work, but 
it will be needed if you want to be able to use your class as the 
key type for associative arrays:
     http://dlang.org/spec/hash-map.html

Anyway, it's not too hard if you understand what's going on, and 
all of the functions I added are good things to have anyway, 
because lots of generic code expects some or all of them. But, 
the error messages aren't all that helpful if you didn't already 
know most of that.


More information about the Digitalmars-d-learn mailing list