I tried to use a function template to encapsulate a lambda expression in
order to call it recursivly. It turned out I wasn't able to use
"=" as lambda initializer, but only "&".
I tried to figure out (stack modell) why this was the case,
without much success.
Can someone please explain why I need to use "by reference (&)" here?
Here a little example:
1 2 3 4 5 6 7 8 9
function<int(int, int)>gcd =
[&](int a, int b) ->int
{
if (a < b) return gcd(b,a);
int rem(a%b);
if (0 == rem) return b;
return gcd(b, rem);
};
I think it is a similar problem as trying to have a recursive type
1 2 3 4
struct A
{
A a;
};
This can't work because A contains an A which contains an A ... it never stops. The size would be be infinite. Same with the lambda if you use [=]. A lambda that contains a lambda that contains a lambda ... . That is why I think you have to capture the lambda by reference.
In the right side of the statement function<>gcd = , the name "gcd" is defined, but refers to the uninitialized block of memory, the object before its constructor has been called.
In the [&] case you bind a reference to that not-yet-living object. Once gcd's constructor finishes, that reference is valid, so that when you, later on, call the function, it correctly calls itself.
In the [=] case, you tell the constructor of the lambda to store a *copy* of the object named "gcd" inside the lambda. And that's what it does: it calls the std::function's copy constructor, giving it the uninitialized std::function (a bunch of random bytes, essentially) as the argument, and that copy constructor crashes at runtime on my gcc. The debugger confirms that the crash occurred in std::function<int(int, int)>::function(const std::function<int(int, int)> &).
@Peter87: an std::function is a container object, which holds a pointer to its target function. It's not like struct A{A a;};, it's more like struct A{vector<A> v;};