On Friday, 15 February 2019 at 14:20:44 UTC, Bastiaan Veelo wrote:
Given a function taking a delegate, for example
```
int fun(int delegate() dg) {return dg();}
```
Sometimes we need to call `fun` with a pointer to a nested
function and other times with a pointer to a top level
function. As function pointers do not implicitly convert to
delegates, this does not work without jumping through hoops.
One option is to define an overload:
```
int fun(int function() fn)
{
int nested_fn()
{
return fn();
}
return fun(&nested_fn);
}
```
This is clunky and rather a lot of extra lines to work around a
language limitation. The limitation seems somewhat artificial,
because a delegate /can/ be initialized referencing a top level
function (the spec [1] limits that to delegate declarations at
module scope, but this limit does not seem to apply [2]). But
you cannot /assign/ it a top level function. You can however
explicitly assign the `.funcptr` referencing the top level
function, leaving the stack frame pointer null.
Exploiting this, it is possible to explicitly convert a
function pointer into a delegate [2]:
```
Ret delegate(Args args) fun_to_dlg(Ret, Args...)(Ret
function(Args args) fun)
{
Ret delegate(Args) dlg;
dlg.funcptr = fun;
return dlg;
}
```
allowing
```
int top_level() {return -1;}
void main()
{
assert(fun(fun_to_dlg(&top_level)) == -1);
}
```
This may be preferable to the overload, depending on the number
of calls like this. But since this is allowed and working, why
can't it be done automatically? Or, when implicit conversion is
dangerous, why doesn't a cast exist to the effect of my
template? Have I overlooked an easier way of doing this?
Thanks for any input!
Bastiaan.
P.S. For the record, the spec also says this: "Future
directions: Function pointers and delegates may merge into a
common syntax and be interchangeable with each other." I wish
that was the case already.
[1] Point 9 in https://dlang.org/spec/function.html#closures
[2] https://run.dlang.io/is/x8HJaW
There is
https://dlang.org/library/std/functional/to_delegate.html