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

Timon Gehr timon.gehr at gmx.ch
Wed Dec 8 07:55:55 UTC 2021


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.

```d
import std.stdio, std.traits, core.lifetime;

struct CtDelegate(R,T...){
     void* ctx;
     R function(T,void*) fp;
     R delegate(T) get(){
         R delegate(T) dg;
         dg.ptr=ctx;
         dg.funcptr=cast(typeof(dg.funcptr))fp;
         return dg;
     }
     alias get this;
     this(void* ctx,R function(T,void*) fp){ this.ctx=ctx; this.fp=fp; }
     R opCall(T args){ return fp(args,ctx); }
}

auto makeCtDelegate(alias f,C)(C ctx){
     static struct Ctx{ C ctx; }
     return 
CtDelegate!(ReturnType!(typeof(f)),ParameterTypeTuple!f[0..$-1])(new 
Ctx(forward!ctx),
           (ParameterTypeTuple!f[0..$-1] args,void* ctx){ auto 
r=cast(Ctx*)ctx; return f(r.ctx,forward!args); });
}

struct A{
     CtDelegate!void[] dg;
}

auto createDelegate(string s){
     return makeCtDelegate!((string s){ s.writeln; })(s);
}

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


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

```


More information about the Digitalmars-d-learn mailing list