Cannot use local lambda as parameter to non-global template
Simen Kjærås
simen.kjaras at gmail.com
Mon Jan 15 15:05:01 UTC 2018
On Monday, 15 January 2018 at 13:55:57 UTC, Nordlöw wrote:
> Why do I get errors like
>
> template instance remove!((_) => _ == 1) cannot use local
> '__lambda5' as parameter to non-global template remove()(in K
> key)
>
> for
>
> x.remove!(_ => _ == 1);
>
> but not for
>
> x.remove!"a == 11";
>
> ?
>
> How are these two lambdas different?
>
> The function `remove` is a templated member of a struct
> instance `x`.
It's a bit involved, but boils down to this: lambdas in D can
only have one context pointer. A simple example:
class Foo {
int n = 2;
int run(alias fun)(int m) { return fun(n, m); }
}
unittest {
int a = 3;
int fn(int n, int m) { return a + n + m; }
assert((new Foo).run!fn(4) == 9);
}
fn obviously requires a pointer to the context in the unittest
block, since it uses 'a' in that context. Somewhat less
obviously, it also needs a pointer to the Foo instance in which
it is run. Since 2 > 1, this fails. There's a bug reported for
it: https://issues.dlang.org/show_bug.cgi?id=5710, and even a
$200 bounty for fixing it:
https://www.bountysource.com/issues/1375082
The bug report is almost seven years old, so it seems this is a
hard bug to squash.
Luckily, there are some workarounds. One you've already found.
Others include moving templates to scopes where less context is
needed (e.g. moving a function template that is associated with a
class, but doesn't need to be part of it, outside the class), and
marking your lambdas 'static'. A static lambda does not have a
context pointer to the scope in which it is declared, and so
cannot use variables declared in it. For instance, fn above uses
'a' in the same scope, and so cannot be marked static.
--
Simen
More information about the Digitalmars-d-learn
mailing list