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

```

Reply via email to