Dispatching from receive to a function
Juanjo Alvarez
juanjux at thatwebmailofgoogleproperty.com
Mon Sep 27 11:46:18 PDT 2010
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;
> }
> }
> }
>
---------------------------------------------------------------------------
More information about the Digitalmars-d-learn
mailing list