I'm new to the language so I don't know if this is horribly wrong on some levels, but it works:
----------------------------- import std.variant; import std.stdio; class C { bool test(int i, char c) { writeln("Hello from test1"); return true; } void test2(string v) { writeln("Hello from test2, ", v); } } void main() { auto c = new C; Variant[string] holder = ["test": Variant(&c.test), "test2": Variant (&c.test2)]; receiver(holder); } void receiver(Variant[string] message) { // If you get the Variant template instantiation delegate // signature wrong, it will // be detected at compile time! auto t = message["test"].get!(bool delegate(int, char)); auto t2 = message["test2"].get!(void delegate(string)); t(1, 'c'); t2("foo"); } -------------------------- Curiously if you create holder like this, it will give an arrayoutofbound error at runtime, I don't know if that is a bug: void main() { auto c = new C; Variant[string] holder; holder["test"] = Variant(&c.test); holder["test2"] = Variant(&c.test2); } On Mon, 27 Sep 2010 18:03:32 +0200, Johannes Pfau wrote: > On 27.09.2010 15:36, Bob Cowdery wrote: >> Thanks. Do you know if the signature is a mandatory part. If I left >> the >> signature out would it then only work with a delegate with no >> parameters? If so I think I'm in the same state as my delegates will >> not all have the same signature. >> >> > Yep, the signature is mandatory. There is another, ugly, unsafe (it's > safe, but you really have to be careful and write correct code) way: > > Basically you cast away the delegates type information. You then store > the delegate in an array. Later, you have to cast the delegate back to > it's original type. The problem here is, that D doesn't provide enough > runtime type information to know which type the delegate originally had, > so _we_ have to store some type info _manually_. This can for example be > done by storing both the delegate and our type info in a struct. > > Here's an example how to do exactly that. > > !!!Note: It's very important to always cast the delegate back to the > _correct_ type before calling it, everything else leads to undefined > behavior!!! So just setting CDelegate.Type to a wrong type can cause a > disaster! > > (Sorry about the bad variable names in the example. For better > encapsulation most of the casts could be moved into the CDelegate struct > by adding functions and constructors) > --------------------------------------------------------------------------- > import std.stdio; > > enum DelegateType > { > A, > B, > C, > D > } > > struct CDelegate > { > void delegate() del; //Exact type doesn't matter, all delegates have > the same size > DelegateType Type; > } > > CDelegate[string] dict; > > class C > { > bool test(int i, char c) {return true;} > } > > class D > { > int test(string s) {return 99;} > } > > void main() > { > C c = new C(); > D d = new D(); > CDelegate custom; > > custom.del = cast(void delegate())&c.test; custom.Type = > DelegateType.C; > dict["c"] = custom; > > custom.del = cast(void delegate())&d.test; custom.Type = > DelegateType.D; > dict["d"] = custom; > > foreach(cdeleg; dict) > { > switch(cdeleg.Type) > { > case DelegateType.C: > bool delegate(int i, char c) realdel = cast (bool > delegate(int i, char c)) cdeleg.del; > writeln(realdel(0, 'c')); > break; > > case DelegateType.D: > int delegate(string) realdel = cast (int > delegate(string)) cdeleg.del; > writeln(realdel("test")); > break; > } > } > } > ---------------------------------------------------------------------------