Function to delegate conversion

Kirk McDonald kirklin.mcdonald at gmail.com
Mon Jun 26 14:39:45 PDT 2006


BCS wrote:
> Kirk McDonald wrote:
> 
>>
>> The following dirty, dirty hack /appears/ to work, at least in this 
>> trivial case:
>>
>> import std.stdio;
>>
>> struct DG {
>>     Object instance;
I think you mean:

-     void function() fn;
+     void* fn;

>> }
>>
>> union U {
>>     DG fake_dg;
>>     void delegate() real_dg;
>> }
>>
>> class A {
>>     void foo() { writefln("A.foo()"); }
>> }
>>
>> void main() {
>>     A a = new A;
>>     void function() fn = &A.foo;
>>
>>     U u;
>>     u.fake_dg.instance = a;
> 
> 
> -     u.fake_dg.fn = fn;
> +     u.fake_dg.fn = cast(void*)fn;
> 
>>
>>     // Call it
>>     u.real_dg();
>> }
>>
> 
> That should also work and won't care about types. But it is still 
> really, really dirty. But it's more portable that the last solution I 
> saw, That one used ASM hacking.

But yes, that is a good idea. Templatizing real_dg, however, is going to 
be a royal pain in the ass, but possible. With Daniel Keep's ftype 
module, we can get something like:

struct DG {
     Object instance;
     void* fn;
}

template dg_unionT(Fn) {
     const uint ARGS = NumberOfArgs!(Fn);
     alias ReturnType!(Fn) RetType;
     union U {
         DG fake_dg;
         static if (ARGS == 0) {
             RetType delegate() real_dg;
         } else static if (ARGS == 1) {
             RetType delegate(ArgType!(Fn, 1)) real_dg;
         } else statif if (ARGS == 2) {
             RetType delegate(ArgType!(Fn, 1), ArgType!(Fn, 2)) real_dg;
         } // and so on...
     }
}

template U(Fn) {
     alias dg_unionT!(Fn).U U;
}

void main() {
     A a = new A;
     auto fn = &A.foo;

     U!(typeof(fn)) u;
     u.fake_dg.instance = a;
     u.fake_dg.fn = cast(void*)fn;

     u.real_dg();
}

Also not pretty, but it should work, insofar as this whole trick works.

-Kirk McDonald



More information about the Digitalmars-d mailing list