Dispatching from receive to a function

Johannes Pfau spam at example.com
Mon Sep 27 09:03:32 PDT 2010


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;
        }
    }
}
---------------------------------------------------------------------------

-- 
Johannes Pfau


More information about the Digitalmars-d-learn mailing list