Cannot implicitly convert delegate to function

pragma pragma_member at pathlink.com
Thu Apr 27 12:36:14 PDT 2006


In article <e2qv42$2gnt$1 at digitaldaemon.com>, Stewart Gordon says...
>
>Jarrett Billingsley wrote:
><snip>
>> The other way around.. I don't think so either.  Something tells me the 
>> mechanism for a delegate call would screw up if the context pointer were 
>> null, or if the function weren't designed to be a delegate. 
>
>But why?  I can't understand why a function that doesn't touch the 
>context pointer at all can't be trivially be converted to a delegate in 
>which the context pointer is null.
>

Well, there's always the trival solution of declaring all of your "functions" as
static members of a class - but that's not always possible. ;)

Direct conversion can be done, but would require DMD to inject a good deal of
code to replace an otherwise simple cast. 

For example, given the following: 

/**/ alias uint function(uint foo,uint bar) FunctionType;
/**/ alias uint function(uint foo,uint bar) Delegatetype;
/**/ FunctionType fn = &myfunc;

An explicit cast from function to delegate is processed:

/**/ Delegatetype dg = cast(DelegateType)&fn;

In response to a function-to-delegate cast, with matching signatures, DMD would
emit code equivalent to this:

/**/ class FunctionTypeDelegate{
/**/     FunctionType fn;
/**/     public this(FunctionType fn){ this.fn = fn; }
/**/     uint dg(uint foo,uint bar){ return fn(foo,bar); }
/**/ }
/**/ DelegateType dg = &((new FunctionTypeDelegate(&fn)).dg);

Using a proxy class/object in this way presents a side-effect-free way to tackle
the problem.  It's also friendly to different calling conventions, as well as
going from one convention to another (the concept could even be useful for
function-to-function and delegate-to-delegate where conventions don't match).

DMD could simply generate the "FunctionTypeDelegate" class and provide it in the
same manner as it would a template (in a COMDAT OMF record).  This way, it won't
cause issues if a cast elsewhere generates the same exact proxy.

Now, this *could* be implemented via a template, barring some limitations.
However, it would take some rather serious hacking to accomplish with the same
kind of simplicity as a cast(), when you could probably hand-code the proxy
above with far less effort (we're talking hours versus seconds, for the first
time around).

$0.02:
Another way to look at it: any one type of delegate is compatible with exactly
one type of function.  So having the compiler interpret a cast() really doesn't
gain you all that much.  You may as well write a proxy for each delegate in
cases where you absolutely have to be compatible with free-functions.  Also,
using proxies is the only way to accept multiple types of delegates in an
abstract way, so it then becomes a matter of using just one convention for
simplicity's sake.

- EricAnderton at yahoo



More information about the Digitalmars-d-learn mailing list