A comparison between C++ and D

Adam D. Ruppe via Digitalmars-d digitalmars-d at puremagic.com
Wed Mar 9 12:14:13 PST 2016


On Wednesday, 9 March 2016 at 18:26:01 UTC, bigsandwich wrote:
> As far as I know capturing other variables requires the GC in D.

You can easily do it yourself with a struct. That's all the c++ 
lambda is anyway, a bit of syntax sugar over a struct.

Then you pass the struct itself if you want the variables carried 
with it, or allocate it somewhere and pass a reference to the 
call operator as a plain delegate.

Let me go into some detail:

---
import std.stdio;

@nogc int delegate(int) dg;

int helper() @nogc {
	int a = 50;
	dg = (b) {
		return a + b;
	};

	return dg(10);
}

void main() {
	writeln(helper());
}
---

That won't compile because it wants to allocate a closure for the 
escaped variable, `a`. How do we get around it?

While keeping the delegate:

---
import std.stdio;

@nogc int delegate(int) dg;

int helper() @nogc {
	int a = 50;

	struct MyFunctor {
		int a;

		@nogc this(int a) { this.a = a; }

		// the function itself
		@nogc int opCall(int b) { return a+b; }
	}

	// capture a by value
         // WARNING: I stack allocated here but
         // set it to a global var, this is wrong;
         // it should probably be malloc'd, but since
         // I know I am just using it here, it is OK
	auto myfunc = MyFunctor(a);

	dg = &myfunc.opCall;

	return dg(10);
}

void main() {
	writeln(helper());
}
---


Like the comment in there says, if you are actually going to be 
storing that delegate, you need to tend to the lifetime of the 
object somehow.

That's a big reason why the GC makes this a lot *nicer* because 
it alleviates that concern, but it isn't *required* - you can 
still manage that object manually if you use the right kind of 
manual caution.

But better is probably to forget the delegate itself (except 
maybe passing it to some places) and actually store that object. 
Then you can pass it by value or refcount it or whatever 
traditional technique you want.

With opCall, this thing counts as functor and std.algorithm will 
treat it as a function too.


What if you want some syntax sugar? Eeeeh, I don't have a full 
solution for that right now, but you could kinda do a mixin 
template or a string thing or something, but I think just doing 
the struct yourself isn't really that bad.


More information about the Digitalmars-d mailing list