Reply to Daniel,

Jarrett Billingsley wrote:

On Tue, Jun 30, 2009 at 11:38 AM, Jesse
Phillips<[email protected]> 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);
}


Reply via email to