December 24, 2006 Function to convert functions to delegates | ||||
---|---|---|---|---|
| ||||
I came up with this function to make it easier to make libraries that can take function pointers or delegates for things like callbacks. Basically it creates a dummy struct to function as the context for the delegate, which then calls the original function. I guess that's a thunk? Anyway: template DelegatizeImpl(alias fn) { private import std.traits; static assert(is(typeof(fn) == function), "Delegatize - input is not a function"); private alias ReturnType!(fn) RetType; private alias ParameterTypeTuple!(fn) ParamTypes; private alias RetType delegate(ParamTypes) DGType; private struct S { RetType func(ParamTypes params) { return fn(params); } } private S context; DGType Delegatize() { return &context.func; } } template Delegatize(alias fn) { alias DelegatizeImpl!(fn).Delegatize Delegatize; } To use it, just make a function: void func(int x, int y) { writefln("func: ", x, ", ", y); } And then call it: auto dg = Delegatize!(func)(); dg(4, 5); // prints "func: 4, 5" The type of the delegate returned will have the same return type and parameter types as the source function. One issue with this is that it doesn't support default parameters -- but then again, D doesn't support that when getting a delegate of an aggregate method period, so there's really no way around it. |
December 24, 2006 Re: Function to convert functions to delegates | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | Jarrett Billingsley wrote: > I came up with this function to make it easier to make libraries that can take function pointers or delegates for things like callbacks. Basically it creates a dummy struct to function as the context for the delegate, which then calls the original function. I guess that's a thunk? Anyway: > [...] > > To use it, just make a function: > > void func(int x, int y) > { > writefln("func: ", x, ", ", y); > } > > And then call it: > > auto dg = Delegatize!(func)(); > dg(4, 5); // prints "func: 4, 5" > I guess that's a common thing to need to do. I wrote one of my own a while back. It trades a bit of a runtime hit (notice the new and assignment) for runtime flexibility (it can take a runtime function pointer). T delegate(A) Fn2Dg(T, A...)(T function(A) f) { struct tmp { typeof(f) fn; T ret(A args){ return fn(args); } }; tmp* ret = new tmp; ret.fn = f; return &ret.ret; } char fn(int i, char j); char delegate(int, char) dg = Fn2Dg(&fn); char function(int, char) fp = &fn; char delegate(int, char) dgr = Fn2Dg(fp); It comes from my paper on D: http://www.webpages.uidaho.edu/~shro822/term_008.pdf |
Copyright © 1999-2021 by the D Language Foundation