Manually allocate delegate?
Adam D. Ruppe via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Jul 12 05:56:16 PDT 2015
On Sunday, 12 July 2015 at 08:38:01 UTC, Tofu Ninja wrote:
> Is it even possible?
Yes, though you need to use an entirely different approach for
closures: make a struct.
Remember that delegates can come from local variable use or a
`this` object being used and work the same way to the outside
world. If it is local variables, the compiler emits the allocate
calls and you have little control over it. If it comes from an
object though, you have much more control: control over what is
stored and control over how it is allocated.
The one notable thing you do NOT control is the delegate's
lifetime. Once it becomes a delegate, it is interchangable with
other delegates and is likely to be mixed in with other things
and the recipient has no way of knowing where it came from.
That's a feature in general, but it also means they can't know if
they have to free() or release_reference() it.... if you need
that, you might use a custom delegate type instead of the built
in one.
Anyway though, just make a struct with the data you need to
capture and a call method, then pass that around.
Before:
void foo() {
int a;
a = 10;
// other code using a
use_delegate( { a++; } );
}
After:
void foo() {
static struct Captures {
int a;
void dg1() { a++; }
}
Captures captures;
with(captures) {
a = 10;
// other code uing a
}
use_delegate(&captures.dg1);
// WARNING: since captures is owned by this scope,
use_delegate had better not hold on to it! But you could just as
well have done Captures* captures = malloc(...) too.
}
So it is slightly more verbose and moves the inline delegate up
to the struct (though if you got clever, you could probably
change that too, like a delegate factory that takes a function
and a this at the call point: dg( (_this) { _this.a++; },
captures); perhaps), but really the extra syntax overhead is
small for real programs anyway.
And the clarity of what is and isn't captured might be worth it.
More information about the Digitalmars-d-learn
mailing list