On 4/19/22 2:18 PM, Andrey Zherikov wrote:
On Tuesday, 19 April 2022 at 16:38:42 UTC, Steven Schveighoffer wrote:
On 4/19/22 11:46 AM, Paul Backus wrote:
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.


I put `static` because it fixes "dual context" error.

So you saw a "dual context" error, and added static, and you got a different error?

This is a bit telling. I think the compiler is maybe thinking that it is inside an aggregate, where it needs a context pointer, and it doesn't actually need one.


Is there a way/workaround to achieve the desired behavior? Those two bugs pointed above were reported in 2017 and 2011 (!) which makes me think that they won't be fixed any time soon (I'm not sure that they are actually the same issue as I faced here).


The dual-context problem is old, and has actually been solved, but then reverted because the mechanism used is not portable to LDC and GDC (i.e. some current code compiles on DMD, but not LDC/GDC).

The other problem is just a straight-up bug.

You can work around the dual context, if you are OK with passing the second context explicitly.

The easiest way is to move the member function to a UFCS function. an example:

```d
struct X
{
   int x;
   void applyToX(alias fn)() {fn(x);}
}

void applyToX_alt(alias fn)(ref X xval) {
   fn(xval.x);
}

void main()
{
   auto s = X(5);
   int y = 6;
   void fn(ref int x) { x += y; }
   s.applyToX!fn; // error, dual context needed
   s.applyToX_alt!fn; // fine, only single context needed
}
```

You might ask, what is the drawback? I mean, it works exactly the same, same usage syntax.

The difference is in what happens when you take a delegate of the function. `&s.applyToX!fn` is very much different than `&s.applyToX_alt!fn`. The latter isn't even possible. But most of the time, there is no intention to take a delegate, so you can get away with the UFCS version.

-Steve

Reply via email to