使用std :: for_each lambda函数的错误

时间:2013-05-26 21:24:53

标签: c++ boost c++11 wt

我有一点问题,我无法弄清楚为什么这段代码不起作用:

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

编译时遇到的错误:

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)'

我正在使用gcc 4.7.3,因此我的编译器可能支持C ++ 11。

userBox_是一个集合,BOOST_FOREACH适用于此代码:

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

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

3 个答案:

答案 0 :(得分:8)

您编写的lambda不捕获任何上下文变量。要做到这一点,最简单的方法是将&添加到lambda的捕获列表中。这将通过引用捕获所有上下文变量,您将能够在lambda中访问它们。

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

我不明白为什么你在循环中打印users.size(),因为看起来每次迭代输出都是一样的。如果将其移到循环外部,并希望对lambda捕获的内容进行更精细的控制,则可以修改捕获列表以仅捕获this指针。这将允许您访问成员变量userBox_

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

MSDN有一篇很好的文章详细解释了lambda expression syntax

最后,在您的情况下,不需要std::for_each和lambda。使用基于范围的for循环将项添加到集合中会更简洁。

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

答案 1 :(得分:1)

您需要知道的一切都在于您收到的错误。

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

userBox_的类型无关紧要,它是一个成员变量,因此lambda需要捕获“this”。

最后,你正在传递值,这意味着你要复制每一个Wt :: WString。您可能希望改为使用

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

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

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

答案 2 :(得分:0)

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

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

users作为只读变量传递。

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

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