std::ref
gives you a lvalue-reference
to something. This reference is wrapped into an object that you can then pass around either by reference or by value.
The expected behavior of the code below is that it prints i is 2
, but it prints i is 1
. Why is that?
Why do I have this expectation? Because I am passing tmp
via std::ref
to wrapper
. In wrapper the reference is then captured by value. I would have assumed that, since I am using std::ref
this value is now still a reference to tmp
. I am changing tmp
and would expect that f
reflects that change.
#include <iostream>
#include <functional>
template<typename F>
auto wrapper(int i, F func) {
return [=]() { return func(i); };
}
void f(int i) {
std::cout << "i is " << i << '\n';
}
int main() {
int tmp = 1;
auto func = wrapper(std::ref(tmp), f);
tmp = 2;
func();
}
The reason this does not work is because your wrapper
function takes an int
as argument.
std::ref
returns a std::reference_wrapper
.
When you pass it to a function that wants an int
you will get an implicit conversion and you arre no longer working with a reference.
If you change your function signature to use a std::reference_wrapper
it will give the intended result.
#include <iostream>
#include <functional>
template<typename F>
auto wrapper(std::reference_wrapper<int> i, F func) {
return [=]() { return func(i); };
}
void f(int i) {
std::cout << "i is " << i << '\n';
}
int main() {
int tmp = 1;
auto func = wrapper(std::ref(tmp), f);
tmp = 2;
func();
}