Any workaround for "closures are not yet supported in CTFE"?

Timon Gehr timon.gehr at gmx.ch
Wed Dec 8 17:05:49 UTC 2021


On 12/8/21 9:07 AM, Petar Kirov [ZombineDev] wrote:
> On Wednesday, 8 December 2021 at 07:55:55 UTC, Timon Gehr wrote:
>> On 08.12.21 03:05, Andrey Zherikov wrote:
>>> On Tuesday, 7 December 2021 at 18:50:04 UTC, Ali Çehreli wrote:
>>>> I don't know whether the workaround works with your program but that 
>>>> delegate is the equivalent of the following struct (the struct 
>>>> should be faster because there is no dynamic context allocation). 
>>>> Note the type of 'dg' is changed accordingly:
>>>
>>> The problem with struct-based solution is that I will likely be stuck 
>>> with only one implementation of delegate (i.e. opCall 
>>> implementation). Or I'll have to implement dispatching inside opCall 
>>> based on some "enum" by myself which seems weird to me. Do I miss 
>>> anything?
>>
>> This seems to work, maybe it is closer to what you are looking for.
>>
>> ...
> 
> Incidentally, yesterday I played with a very similar solution. Here's my 
> version:
> 
> https://run.dlang.io/gist/PetarKirov/f347e59552dd87c4c02d0ce87d0e9cdc?compiler=dmd 
> 
> 
> 
> ```d
> interface ICallable
> {
>      void opCall() const;
> }
> 
> auto makeDelegate(alias fun, Args...)(auto ref Args args)
> {
>      return new class(args) ICallable
>      {
>          Args m_args;
>          this(Args p_args) { m_args = p_args; }
>          void opCall() const { fun(m_args); }
>      };
> }
> 
> alias Action = void delegate();
> 
> Action createDelegate(string s)
> {
>      import std.stdio;
>      return &makeDelegate!((string str) => writeln(str))(s).opCall;
> }
> 
> struct A
> {
>      Action[] dg;
> }
> 
> A create()
> {
>      A a;
>      a.dg ~= createDelegate("hello");
>      a.dg ~= createDelegate("buy");
>      return a;
> }
> 
> void main()
> {
>      enum a = create();
>      foreach(dg; a.dg)
>          dg();
> }
> ```

Nice, so the error message is lying. This is a bit more complete:

```d
import std.stdio, std.traits, core.lifetime;
auto partiallyApply(alias fun,C...)(C context){
     return &new class(move(context)){
         C context;
         this(C context) { foreach(i,ref c;this.context) 
c=move(context[i]); }
         auto opCall(ParameterTypeTuple!fun[context.length..$] args) {
             return fun(context,forward!args);
         }
     }.opCall;
}

alias Action = void delegate();

Action createDelegate(string s){
     import std.stdio;
     return partiallyApply!((string str) => writeln(str))(s);
}

struct A{ Action[] dg; }

A create(){
     A a;
     a.dg ~= createDelegate("hello");
     a.dg ~= createDelegate("buy");
     return a;
}

void main(){
     enum a = create();
     foreach(dg; a.dg)
         dg();
}

```


More information about the Digitalmars-d-learn mailing list