简体   繁体   中英

Using member variable in lambda capture list inside a member function

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?

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.

Summary of the alternatives:

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

我相信,你需要抓住this

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, eg

auto& localGrid = grid;
int i;
for_each(groups.cbegin(),groups.cend(),[localGrid,&i](pair<int,set<int>> group){
            i++;
            cout<<i<<endl;
   });

To use the member variables inside Lambda expression in VS2010 and so on, you need to capture this pointer in capture list.

Please refer below sample code:

class A
{
    public:
    std::map<string, TicketInfo>  m_mapImanFileUIDTicket;
    void Myfunction();
};

void A::Myfunction()
{
    std::string Filename;
    NameRef namedRefOutput;

    auto lambdaGetReadTicket = [FileName, namedRefOutput, this]()
    {
        TicketInfo      Info;
        Info.fileName = FileName;
        Info.ticket = namedRefOutput.ticket;
        m_mapImanFileUIDTicket[FileName] = Info; //This member variable defined in class
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM