如何为std :: fill()使用C ++ 0x lambdas局部变量?

时间:2011-07-10 06:50:54

标签: c++ c++11 lambda fill iota

所以我试图测试一个lambda访问它所使用的范围内的局部变量,大致基于Bjarne在C ++ 0x FAQS页面上的一个简单例子: http://www2.research.att.com/~bs/C++0xFAQ.html#lambda

当我尝试这个简单的测试代码时:

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

//Test std::fill() with C++0x lambda and local var
void f (int v) { 
    vector<int> indices(v);
    int count = 0;
    fill(indices.begin(), indices.end(), [&count]() {
        return ++count;
    });

    //output test indices
    for (auto x : indices) {
        cout << x << endl;
    }
}

int main() {
    f(50);
}

我收到错误:

required from 'void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, _Tp = f(int)::<lambda()>]'

我想这个errmsg表明std :: fill()签名需要一个const Type&amp;用于新的值元素赋值。

但是如果我能够为此目的使用fill(),正如Bjarne的例子所示,我不需要在lambda capture子句中使用引用'[&amp; count]'来能够通过'return ++ count;'将原始索引元素值与递增计数var重新分配lambda语句块?

我承认我还不太了解这些lambdas! :)

3 个答案:

答案 0 :(得分:15)

Bjarne的例子没有编译。除非他们在C ++ 0x中以不同的方式定义std::fill,否则它无法编译。也许它来自std::fill的一个可以采用函数的特征版本,但它的实际版本(根据N3242的第25.1节)采用对象,而不是函数。它将该对象复制到列表的每个元素中。这就是那个人想要做的事情。

您正在寻找的功能是std::generate

答案 1 :(得分:1)

试试这个:

for_each(indices.begin(), indices.end(), [&count](int& it) 
{        
    it = ++count;    
});

it目前是迭代的向量内容,通过引用来发布。

答案 2 :(得分:1)

我希望可以添加“更新”风格的答案,以便将来可能有同样问题的读者受益。请告诉我,因为我是新来的。

所以,这是我最终重做的代码形式,它做了我想要的:

#include <iostream>
#include <vector>
#include <algorithm>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    int index{ base };
    std::generate(ints.begin(), ints.end(), [&index]() {
        return index++;  //post-incr.
    });
}

//Default wrapper to overwrite a vector<int> 
// with incrementing values, base-0.
void init_integers(std::vector<int>& ints) {
    init_integers(ints, 0);
}

//Test lambda-based vector<int> initialization.
int main() {
    std::vector<int> indices( 50 );
    init_integers(indices);

    //test output loaded indices.
    for (auto x : indices) {
        std::cout << x << std::endl;
    }
}

感谢您提供有用的答案,我发现这是一种更简单的方法。从现在开始,我很可能会使用lambdas来获取带有函数对象的算法!



更新2:

基于ildjarn对上述原帖的评论: “请注意,此处的确切功能是通过新的C ++ 0x算法实现的 - std :: iota。”

经过测试,我已将相应的代码修改为:

...
#include <numeric>

//Overwrite a vector<int> with incrementing values, base-n.
void init_integers(std::vector<int>& ints, int base) {
    std::iota(ints.begin(), ints.end(), base);
}
...

它工作正常。 (“Iota”,s26.7.6,N3242)。

更简单,更清晰(虽然有点模糊),更容易阅读 - 更重要的是 - 维护。

谢谢ildjarn! (虽然亲自完成这个过程以获得对C ++ 0x lambdas的进一步了解是一个很好的练习!):) -Bud Alverson