The following code compiles with gcc 4.5.1 but not with VS2010 SP1:
#include <iostream>
#include <vector>
#include <map>
#include <utility>
#include <set>
#include <algorithm>
using namespace std;
class puzzle
{
vector<vector<int>> grid;
map<int,set<int>> groups;
public:
int member_function();
};
int puzzle::member_function()
{
int i;
for_each(groups.cbegin(),groups.cend(),[grid,&i](pair<int,set<int>> group){
i++;
cout<<i<<endl;
});
}
int main()
{
return 0;
}
This is the error:
error C3480: 'puzzle::grid': a lambda capture variable must be from an enclosing function scope
warning C4573: the usage of 'puzzle::grid' requires the compiler to capture 'this' but the current default capture mode does not allow it
So,
1> which compiler is right?
2> How can I use member variables inside a lambda in VS2010?
This question is related to
c++
visual-studio-2010
lambda
c++11
I believe VS2010 to be right this time, and I'd check if I had the standard handy, but currently I don't.
Now, it's exactly like the error message says: You can't capture stuff outside of the enclosing scope of the lambda.† grid
is not in the enclosing scope, but this
is (every access to grid
actually happens as this->grid
in member functions). For your usecase, capturing this
works, since you'll use it right away and you don't want to copy the grid
auto lambda = [this](){ std::cout << grid[0][0] << "\n"; }
If however, you want to store the grid and copy it for later access, where your puzzle
object might already be destroyed, you'll need to make an intermediate, local copy:
vector<vector<int> > tmp(grid);
auto lambda = [tmp](){}; // capture the local copy per copy
† I'm simplifying - Google for "reaching scope" or see §5.1.2 for all the gory details.
An alternate method that limits the scope of the lambda rather than giving it access to the whole this
is to pass in a local reference to the member variable, e.g.
auto& localGrid = grid;
int i;
for_each(groups.cbegin(),groups.cend(),[localGrid,&i](pair<int,set<int>> group){
i++;
cout<<i<<endl;
});
I believe, you need to capture this
.
capture this
:
auto lambda = [this](){};
use a local reference to the member:
auto& tmp = grid;
auto lambda = [ tmp](){}; // capture grid by (a single) copy
auto lambda = [&tmp](){}; // capture grid by ref
C++14:
auto lambda = [ grid = grid](){}; // capture grid by copy
auto lambda = [&grid = grid](){}; // capture grid by ref
example: https://godbolt.org/g/dEKVGD
Source: Stackoverflow.com