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