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();
}
```