import std.traits; template typehash(T...) { void delegate(T) tmp; enum typehash = hashOf(tmp.mangleof.ptr, tmp.mangleof.length); } alias void delegate(void*) wrapper; wrapper[hash_t] listeners; void addListener(T)(T t) if(ParameterTypeTuple!(T).length == 1) { listeners[typehash!(ParameterTypeTuple!(T)[0])] = (void* ptr) { t(*(cast(ParameterTypeTuple!(T)[0]*) ptr)); }; } void send(T)(T t) { auto hash = typehash!T; auto func = hash in listeners; if(func is null) { writeln("no listener"); return; } (*func)(cast(void*) &t); } struct Test {} import std.stdio; void main() { addListener(delegate void(int a) { writeln("got ", a); }); addListener(delegate void(File a) { writeln("got ", a); }); send(20); send(stdin); } // the following is copy/pasted from druntime src/rt/util/hash.d // is that available as an import somewhere in the stdlib? version( X86 ) version = AnyX86; version( X86_64 ) version = AnyX86; version( AnyX86 ) version = HasUnalignedOps; @trusted pure nothrow hash_t hashOf( const (void)* buf, size_t len, hash_t seed = 0 ) { /* * This is Paul Hsieh's SuperFastHash algorithm, described here: * http://www.azillionmonkeys.com/qed/hash.html * It is protected by the following open source license: * http://www.azillionmonkeys.com/qed/weblicense.html */ static uint get16bits( const (ubyte)* x ) pure nothrow { // CTFE doesn't support casting ubyte* -> ushort*, so revert to // per-byte access when in CTFE. version( HasUnalignedOps ) { if (!__ctfe) return *cast(ushort*) x; } return ((cast(uint) x[1]) << 8) + (cast(uint) x[0]); } // NOTE: SuperFastHash normally starts with a zero hash value. The seed // value was incorporated to allow chaining. auto data = cast(const (ubyte)*) buf; auto hash = seed; int rem; if( len <= 0 || data is null ) return 0; rem = len & 3; len >>= 2; for( ; len > 0; len-- ) { hash += get16bits( data ); auto tmp = (get16bits( data + 2 ) << 11) ^ hash; hash = (hash << 16) ^ tmp; data += 2 * ushort.sizeof; hash += hash >> 11; } switch( rem ) { case 3: hash += get16bits( data ); hash ^= hash << 16; hash ^= data[ushort.sizeof] << 18; hash += hash >> 11; break; case 2: hash += get16bits( data ); hash ^= hash << 11; hash += hash >> 17; break; case 1: hash += *data; hash ^= hash << 10; hash += hash >> 1; break; default: break; } /* Force "avalanching" of final 127 bits */ hash ^= hash << 3; hash += hash >> 5; hash ^= hash << 4; hash += hash >> 17; hash ^= hash << 25; hash += hash >> 6; return hash; }