Hello Christof!
I've been tripped up in a similar way using std::function<>.
As Alf pointed out and you've concluded, when you call
your Container constructor and pass it a Functor
1) the compiler creates a temporary std::function<> that
contains, in essence, a copy of your Functor, and
2) when you take a reference to this std::function, you
end up with a dangling reference.
What I've done in the past to get the behavior I think
you want is to use std::ref.
Here's a modified version of your example that illustrates
this:
#include <iostream>
using std::cout;
using std::endl;
#include <functional>
struct Container {
Container (std::function<void()> functor) : functor_(functor) {}
std::function<void()> functor_;
};
struct Functor {
Functor (int i) : i_(i) {}
void operator()() {
cout << i_++ << endl;
}
int i_;
};
int main() {
Functor functor(42);
functor();
functor();
Container container(std::ref(functor));
container.functor_();
container.functor_();
functor();
return 0;
}
Notice that I've added the i_++, so that the state in
Functor gets modified.
I've purposely called functor() and container.functor_()
multiple times to illustrate that you pass the state
contained in functor into container, and that you get the
modified state out again, not only in container.functor_,
but in functor, as well.
That is, you really do get reference semantics to your
original functor.
Notice that Container now uses value semantics, and that
the client of container has to explicitly use reference
semantics via std::ref to get the desired behavior. This
is presumably an imperfection in Container's interface,
but I think it's the price you have to pay for using
std::function, which is inherently value-based.
To comment a little bit further:
std::function seems like a great idea -- it holds anything
that "acts like a function." So you can use functions,
explicit function objects, lambdas, etc.
But when would you want to use a function object instead of
a plain function? The common reason is because you want your
function object to contain some state. You can use the value
semantics of std::function, and, in effect, make a copy of
your function object if all you want to do is pass state in
(a common use of function objects), but not if you want to
get (mutable) state back out into your original function object.
The only way I know how to do this (in a reasonably
straightforward way) with std::function is to make the client
explicitly use reference semantics with std::ref.
This seems to be a limitation of std::function (not that I
have a proposal to fix it), and it tripped me up along the
same lines you describe in your post when I first tried to
take advantage of the convenience of std::function.
> Thank you so much,
>
> Chris
Happy Hacking!
K. Frank