Question

I have a little problem and I can't figure out why this code doesn't work:

std::for_each(users.begin(), users.end(), [](Wt::WString u)
{
    std::cout << "ilosc: " << users.size() << std::endl;
    userBox_->addItem(u);
});

Errors that I get while compiling:

GameWidget.cpp: In lambda function:
GameWidget.cpp:352:30: error: 'users' is not captured
GameWidget.cpp:353:4: error: 'this' was not captured for this lambda function
GameWidget.cpp: In member function 'virtual void GameWidget::updateUsers()':
GameWidget.cpp:354:3: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]
GameWidget.cpp:354:4: error: no matching function for call to 'for_each(std::set<Wt::WString>::iterator, std::set<Wt::WString>::iterator, GameWidget::updateUsers()::<lambda(Wt::WString)>)'
GameWidget.cpp:354:4: note: candidate is:
In file included from /usr/include/c++/4.7/algorithm:63:0,
                 from GameWidget.h:11,
                 from GameWidget.cpp:9:
/usr/include/c++/4.7/bits/stl_algo.h:4436:5: note: template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)
GameWidget.cpp:354:4: error: template argument for 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)' uses local type 'GameWidget::updateUsers()::<lambda(Wt::WString)>'
GameWidget.cpp:354:4: error:   trying to instantiate 'template<class _IIter, class _Funct> _Funct std::for_each(_IIter, _IIter, _Funct)'

I am using gcc 4.7.3, so probably C++11 support is available for my compiler.

userBox_ is a collection and BOOST_FOREACH works properly for this code:

BOOST_FOREACH(Wt::WString i, users)
{
    std::cout << "ilosc: " << users.size() << std::endl;
    userBox_->addItem(i);
}

Thanks for any answer, I'm so curious why is that.

Était-ce utile?

La solution

The lambda you've written does not capture any context variables. To do this, the easiest is to add & to the lambda's capture list. This will capture all context variables by reference and you'll be able to access them within the lambda.

std::for_each(users.begin(), users.end(), [&](Wt::WString u)
{
    std::cout << "ilosc: " << users.size() << std::endl;
    userBox_->addItem(u);
});

I don't understand why you're printing users.size() within the loop, because it looks like the output is going to be the same every iteration. If you move that outside the loop, and want more fine grained control over what the lambda captures, you can modify the capture list to only capture the this pointer. This will let you access the member variable userBox_.

std::cout << "ilosc: " << users.size() << std::endl;
std::for_each(users.begin(), users.end(), [this](Wt::WString u)
{
    userBox_->addItem(u);
});

MSDN has an excellent article explaining the lambda expression syntax in great detail.

Finally, in your case, there's no need for std::for_each and a lambda. It would be a lot more succinct to use a range based for loop to add the items to the collection.

for( auto const& u: users ) {
  userBox_->addItem(u);
}

Autres conseils

Everything you needed to know is in the errors you received.

You told the lambda, explicitly, not to capture anything, by using "[]", which means the only variables it has access to inside the function body are parameters and globals.

It doesn't matter what type userBox_ is, it's a member variable, so the lambda needs to capture "this".

Lastly, you're passing by value, which means you're going to duplicate each and every Wt::WString. You might want instead to use

std::for_each(users.begin(), users.end(), [&](const Wt::WString& u) {
...
});

The "&" captures by reference and will capture "this" for you.

http://en.cppreference.com/w/cpp/language/lambda

Capturing the variable users means declaring your lambda as:

    [users](Wt::WString u){...}

which will pass users as a read-only variable.

To be able to modify users, you need to declare your lambda as:

    [&users](Wt::WString u){...}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top