Combining Delegate and Functions
BCS
ao at pathlink.com
Tue Jun 30 12:27:20 PDT 2009
Reply to Daniel,
> Jarrett Billingsley wrote:
>
>> On Tue, Jun 30, 2009 at 11:38 AM, Jesse
>> Phillips<jessekphillips at gmail.com> wrote:
>>> So looking at a post on StackOverflow about D gatchas:
>>> http://stackoverflow.com/questions/743319/why-isnt-the-d-language-pi
>>> cking-up/1059780#1059780
>>>
>>> "functions that form closures or are attached to objects (ie.
>>> methods) are not the same as regular functions, instead they are
>>> called delegates, and you must be aware of the differences."
>>>
>>> I seem to recall the distinction was going to be going away or
>>> minimized. Is this already done? Will it be going into D2?
>>>
>> Nothing's changed in that area. Theoretically the compiler could
>> implicitly convert function pointers to delegates by creating thunks.
>> It shouldn't be *that* hard to implement..
>>
> Here's something I have in a project of mine. I didn't come up with
> the idea, but I forget who did.
>
> Note that this is not generalised. I started working on a general
> one, but gave up when it proved too fiddly and difficult to correctly
> rebuild a function's argument list.
>
> /*
> * This is utterly evil, but also REALLY cool.
> *
> * What we do here is make a dummy struct, and give it a member
> * function. The member function has a hidden argument (this).
> *
> * We then construct a delegate of the appropriate type, set its
> * funcptr to Wrap.call and its ptr to the function pointer.
> *
> * When dg is called, it is called as (dg.funcptr(dg.ptr, ...))
> * which is the same way the (this) argument of member functions
> * is passed.
> *
> * Thus, inside the member function, we can cast the this pointer
> * back to our function pointer and call it.
> */
> struct Wrap
> {
> void call(Context a, PullParserSlice b)
> {
> return (cast(void function(Context, PullParserSlice)) this)
> (a,b);
> }
> }
> ElementBinding.Handler dg;
> Wrap wrap;
> dg.ptr = handler;
> dg.funcptr = cast(typeof(dg.funcptr)) &wrap.call;
here's a general version that should work but dosn't:
struct Wraper(F)
{
static if(is(F Fn == Fn*) && is(Fn A == function) && is(Fn R == return))
{
static assert(is(F == R function(A)));
union U
{
Wraper* w;
F f;
}
R Call(A a) /// BUG: this drops ref and out on A
{
static assert(is(F == R function(A)));
U u;
u.w = this;
return u.f(a);
}
alias R delegate(A) ret;
}
else
static assert(false, "Can't use "~Fn.stringof);
}
Wraper!(F).ret Wrap(F)(F f)
{
Wraper!(F).U u;
u.f = f;
return &u.w.Call;
}
int foo(ref int i, out float x, char[] c)
{
x = 3.14;
return i += c.length;
}
import std.stdio;
void main()
{
auto dg = Wrap(&foo);
float f = 2.717;
int i = 3;
char[] c = "Hello world";
auto j = dg(i, f, c);
writef("i=%s, j=%s, f=%s\n", i,j,f);
}
More information about the Digitalmars-d
mailing list