开发者

How to use C++0x lambdas local variables for std::fill()?

So I was trying to test a lambda accessing local variables in the scope in which it is used, based roughly on a simple example by Bjarne on the C++0x FAQS page at: http://www2.research.att.com/~bs/C++0xFAQ.html#lambda

When I try this simple test code:

#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);
}

I get the error:

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

I'm supposing this errmsg indicates the std::fill() signature requires a const Type& to use for the new value element assignment.

But if I'm to be able to use the fill() for this purpose, as indicated by Bjarne's example, won't I need to use a reference '[&count]' inside the lambda capture clause to be able to开发者_运维技巧 reassign the original indices element value with the incrementing count var via the 'return ++count;' lambda statement block?

I admit I don't quite understand all about these lambdas just yet! :)


Bjarne's example doesn't compile. It can't compile, not unless they defined std::fill differently in C++0x. Maybe it was from a conceptized version of std::fill that could take a function, but the actual version of it (according to section 25.1 of N3242) takes an object, not a function. It copies that object into every element of the list. Which is what that one is trying to do.

The function you're looking for is std::generate.


Try this:

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

it is currently iterated content of vector, and is coming via reference.


I hope it's OK to add an "update" style answer, for the benefit of any future readers who may have this same question. Please let me know since I'm new here.

So, here's my final reworked form of the code that does what I'm wanting:

#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;
    }
}

Thanks for the helpful answers, I find this a much easier approach. I'll very likely be using lambdas from now on for algorithms that take a function object!



Update 2:

Based on ildjarn's comment to the original post above: "Note that the exact functionality here is implemented by a new C++0x algorithm -- std::iota."

After testing, I've modified the appropriate code to:

...
#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);
}
...

and it's working fine. ("Iota", s26.7.6, of N3242).

The simpler and cleaner (though a bit obscure), the easier to read--and more importantly--maintain.

Thanks ildjarn! (Though it was a good exercise personally to go through this process to pick up some further insight on the C++0x lambdas!) :) -Bud Alverson

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜