Generalizing over function pointers and delegates

Bastiaan Veelo Bastiaan at Veelo.net
Fri Feb 15 14:20:44 UTC 2019


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


More information about the Digitalmars-d-learn mailing list