Reputation: 6046
I've recently opened this discussion, from which the following problem comes from. This question is a sort of continuous of that discussion. Here is the code:
#include <iostream>
#include <functional>
using namespace std;
std::function<int(void)> mylambda(int starter){
return [starter]() mutable {
return ++starter;
};
}
void tester_wrapper(const std::function<int(void)>& cb, int counter){
if (counter == 10)
return;
else{
cout << cb() << endl;
tester_wrapper(cb, counter + 1);
}
}
void tester(const std::function<int(void)>& cb){
tester_wrapper(cb, 0);
}
int main()
{
auto getNum = mylambda(1);
tester(getNum);
tester(getNum);
}
In this case the code does what I expected, more specifically it prints all number from 2 to 21. However if my main
function was like this:
int main()
{
auto getNum = ([](int starter) {
return [starter]() mutable {
return ++starter;
};
})(1);
tester(getNum);
tester(getNum);
}
Then the output would be numbers from 2 to 11 repeated twice. I can't explain myself why it produces this output even if the only difference between the 2 pieces of code is where and how the mylambda
function is defined.
Upvotes: 5
Views: 216
Reputation: 170153
Because the lambda closure type and std::function
are not reference related. Those are separate types. You can't bind a reference to std::function
directly to a lambda object.
A lambda object is convertible to a std::function
however. So what happens is that the compiler creates a temporary std::function
that binds to that const reference. Creating very much the same situation in your original question. Because each call to tester
necessitates another temporary object. Temporaries only live to the end of the full expression that makes them spring to life.
In the first code sample, you already have a std::function
object in main. That one binds directly to the reference, so you are calling tester
with the same referred-to object.
Upvotes: 8