Polymorphic hashOf

Per Nordlöw per.nordlow at gmail.com
Sat Dec 22 22:36:31 UTC 2018


If I want to include the class type (TypeInfo) inside a class 
instance hash, is the following snippet a good `@safe pure 
nothrow @nogc`-solution?:


import core.internal.hash : hashOf;

/** Hash that distinguishes `Expr(X)` from `NounExpr(X)`. */
hash_t hashOfPolymorphic(Class)(Class aClassInstance) @trusted 
pure nothrow @nogc
if (is(Class == class))
{
     assert(Class.alignof == 8);
     return (cast(hash_t)(cast(void*)typeid(Class)) >> 3) ^ 
hashOf(aClassInstance);
}

class Thing
{
}

class Expr : Thing
{
     @safe pure nothrow @nogc:
     alias Data = string;
     this(Data data)
     {
         this.data = data;
     }
     @property override hash_t toHash() const @safe pure nothrow 
@nogc
     {
         return hashOf(data);
     }
     Data data;
}

class NounExpr : Expr
{
     @safe pure nothrow @nogc:
     this(Data data)
     {
         super(data);
     }
     @property override hash_t toHash() const @safe pure nothrow 
@nogc
     {
         return hashOf(data);
     }
}

class Year : Thing
{
     @safe pure nothrow @nogc:
     alias Data = long;
     @property override hash_t toHash() const @safe pure nothrow 
@nogc
     {
         return hashOf(data);
     }
     Data data;
}

@safe pure nothrow unittest
{
     auto car1 = new Expr("car");
     auto car2 = new Expr("car");
     auto bar1 = new Expr("bar");
     auto ncar = new NounExpr("car");

     void testEqual() @safe pure nothrow @nogc
     {
         assert(hashOf(car1) == hashOf(car2));
         assert(hashOfPolymorphic(car1) == 
hashOfPolymorphic(car2));
     }

     void testDifferent1() @safe pure nothrow @nogc
     {
         assert(hashOf(car1) != hashOf(bar1));
         assert(hashOfPolymorphic(car1) != 
hashOfPolymorphic(bar1));
     }

     void testDifferent2() @safe pure nothrow @nogc
     {
         assert(hashOf(car1) == hashOf(ncar));
         assert(hashOfPolymorphic(car1) != 
hashOfPolymorphic(ncar));
     }

     testEqual();
     testDifferent1();
     testDifferent2();
}



More information about the Digitalmars-d-learn mailing list