I have the following code (compiler: MSVC++ 10):
std::vector<float> data;
data.push_back(1.0f);
data.push_back(1.0f);
data.push_back(2.0f);
// lambda expression
std::for_each(data.begin(), data.end(), [](int value) {
// Can I get here index of the value too?
});
What I want in the above code snippet is to get the index of the value in the data vector inside the lambda expression. It seems for_each only accepts a single parameter function. Is there any alternative to this using for_each and lambda?
You could also pass a struct as third argument to std::for_each and count the index in it like so:
In C++14 thanks to generalized lambda captures you can do something like so:
Roger Pate suggested in a comment to my other answer creating an iterator wrapper that performs the enumeration. Implementing it was a bit of a beating.
This iterator wrapper takes a forward iterator whose value type is
T
(called the "inner iterator") and transforms it into a forward iterator whose value type is apair<int, T&>
, whereint
is the distance type of the inner iterator.This would be quite simple, except for two things:
std::pair
constructor takes its arguments by const reference so we can't initialize a data member of typeT&
; we'll have to create our own pair type for the iterator.operator*
needs to return a reference andoperator->
needs to return a pointer), so the pair needs to be a data member of the iterator. Since it contains a reference, we'll need a way to "reset" it and we'll need it to be lazily initialized so that we can correctly handle end iterators.boost::optional<T>
seems not to like it ifT
is not assignable, so we'll write our own simplelazy<T>
.The
lazy<T>
wrapper:The
enumerating_iterator
:A test stub:
This has been minimally tested; Comeau and g++ 4.1 both accept it if I remove the C++0x type traits and
aligned_storage
(I don't have a newer version of g++ on this laptop to test with). Please let me know if you find any bugs.I'm very interested in suggestions about how to improve this. Specifically, I'd love to know if there is a way around having to use
lazy<T>
, either by using something from Boost or by modifying the iterator itself. I hope I'm just being dumb and that there's actually a really easy way to implement this more cleanly.Something like this:
Used as:
Another way to wrap iterators for enumerate:
Required headers:
Wrapping iterator:
Enumerate overloads:
Copied test from James:
I don't include providing an offset here; though it's fully ready in EnumerateIterator to start at otherwise than 0. The choice left is what type to make the offset and whether to add overloads for the extra parameter or use a default value. (No reason the offset has to be the iterator's difference type, e.g. what if you made it some date related type, with each iteration corresponding to the next day?)
Alternatively, you can use &value - &data[0], although it might be a bit more expensive.