使用std::for_each lambda函数出现错误

时间:2022-11-10 18:03:06

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.

我使用的是gcc 4.7.3,所以我的编译器可能支持c++ 11。

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

userBox_是一个集合,BOOST_FOREACH可以正确地为这段代码工作:

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.

谢谢你的回答,我很好奇为什么会这样。

3 个解决方案

#1


7  

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.

您所编写的lambda没有捕获任何上下文变量。要做到这一点,最简单的方法是添加&到lambda的捕获列表。这将通过引用捕获所有上下文变量,您将能够在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_.

我不明白为什么要在循环中打印user .size(),因为看起来每次迭代的输出都是相同的。如果您将其移到循环之外,并希望对lambda捕获的内容进行更细粒度的控制,您可以修改捕获列表,只捕获该指针。这将允许您访问成员变量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.

MSDN有一篇出色的文章详细解释lambda表达式语法。

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.

最后,在您的例子中,不需要std: for_each和一个lambda。使用基于范围的for循环将项目添加到集合中要简洁得多。

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

#2


1  

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.

您明确地告诉lambda,不要使用“[]”来捕获任何内容,这意味着它在函数体中唯一可以访问的变量是参数和全局变量。

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

userBox_是什么类型并不重要,它是一个成员变量,所以lambda需要捕获“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

最后,要传递值,这意味着要复制每个Wt::WString。你可能想用

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

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

“&”通过引用捕获,并将为您捕获“this”。

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

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

#3


0  

Capturing the variable users means declaring your lambda as:

捕获变量用户意味着将lambda声明为:

    [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:

为了能够修改用户,您需要将lambda声明为:

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

#1


7  

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.

您所编写的lambda没有捕获任何上下文变量。要做到这一点,最简单的方法是添加&到lambda的捕获列表。这将通过引用捕获所有上下文变量,您将能够在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_.

我不明白为什么要在循环中打印user .size(),因为看起来每次迭代的输出都是相同的。如果您将其移到循环之外,并希望对lambda捕获的内容进行更细粒度的控制,您可以修改捕获列表,只捕获该指针。这将允许您访问成员变量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.

MSDN有一篇出色的文章详细解释lambda表达式语法。

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.

最后,在您的例子中,不需要std: for_each和一个lambda。使用基于范围的for循环将项目添加到集合中要简洁得多。

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

#2


1  

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.

您明确地告诉lambda,不要使用“[]”来捕获任何内容,这意味着它在函数体中唯一可以访问的变量是参数和全局变量。

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

userBox_是什么类型并不重要,它是一个成员变量,所以lambda需要捕获“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

最后,要传递值,这意味着要复制每个Wt::WString。你可能想用

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

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

“&”通过引用捕获,并将为您捕获“this”。

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

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

#3


0  

Capturing the variable users means declaring your lambda as:

捕获变量用户意味着将lambda声明为:

    [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:

为了能够修改用户,您需要将lambda声明为:

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