On 4/19/22 11:46 AM, Paul Backus wrote:
On Tuesday, 19 April 2022 at 13:36:26 UTC, Andrey Zherikov wrote:
I want to migrate my library API from standalone function that takes delegate as argument to a template member function that takes delegate as a template parameter but compiler errors out. Here is code example:
```d
import std.stdio;

template T(P)
{
    static void f_new(alias func)()
    {
        func();
    }
}

void f(FUNC)(FUNC func)
{
    T!int.f_new!(() => func());
}

void main()
{
    f(function () { __LINE__.writeln; });
}
```

Compiler error:
```
onlineapp.d(7): Error: `static` function `onlineapp.f!(void function() @safe).f.f_new!(delegate () @safe
{
(*func)();
return ;
}
).f_new` cannot access delegate `__lambda2` in frame of function `onlineapp.f!(void function() @safe).f`
onlineapp.d(13):        `__lambda2` declared here
onlineapp.d(13): Error: template instance `onlineapp.f!(void function() @safe).f.f_new!(delegate () @safe
{
(*func)();
return ;
}
)` error instantiating
onlineapp.d(18):        instantiated from here: `f!(void function() @safe)`
```

What confuses me a lot is that if I remove `template T` then everything works perfectly:

The message is different, but I think this error is probably related to the "dual context" issue:

https://issues.dlang.org/show_bug.cgi?id=5710

Basically, `f_new!(() => func())` has two scopes that it "wants" to be nested in: `T!int` and `f!(void function() @safe)`. When you remove `template T`, there's only one scope, so it's not a problem.

No, there is no context pointer necessary for a template instantiation, without one being artificially introduced via an alias parameter. `T!int` is essentially just a namespace, especially since the `P` parameter isn't even used.


If you remove `static` from `f_new`, you get an error message talking about this explicitly:

Interesting that `static` does anything there, since it's a no-op.

-Steve

Reply via email to