The lambda notation has made stl algorithms more accessible. I am still learning to decide when it’s useful and when to fall back to good old fashioned for-loops.
Often, it becomes necessary to iterate over two (or more) containers of the same size, such that corresponding elements are related, but for some reason are not packed into the same class.
A function using a for-loop to achieve that would look like this:
template<typename Data, typename Property>
void foo(vector<Data>& data, vector<Property>& prop) {
auto i_data = begin(data);
auto i_prop = begin(prop);
for (; i_data != data.end(); ++i_data, ++i_prop) {
if (i_prop->SomePropertySatistfied()) {
i_data->DoSomething();
}
}
}
In order to use for_each, I need a version of it that handles multiple ranges; something like:
template<typename InputIter1, typename InputIter2, typename Function>
Function for_each_on_two_ranges(InputIter1 first1, InputIter1 last1, InputIter2 first2, Function f) {
for (; first1 != last1; ++first1, ++first2) {
f(*first1, *first2);
}
return f;
}
With this version, the above code would look like this:
template<typename Data, typename Property>
void foo_two_ranges(vector<Data>& data, vector<Property>& prop) {
for_each_on_two_ranges(begin(data), end(data), begin(prop), [](Data& d, Property& p) {
if (p.SomePropertySatistfied()) {
d.DoSomething();
}
});
}
Is there an equivalent way of achieving the same result using stl algorithms?
EDIT
I found the exact answer to my question in the form of boost::for_each running on boost::range. I added the answer, with example code for the sake of completeness.
1) The algorithms in the STL are not meant to cover every possible case, if you need
for_each_on_two_rangesthen write it (as you have) and use it. The beauty of the STL is it’s so extensible, and you’ve extended it with a useful new algo.2) If that doesn’t work, you don’t have to use good old fashioned for-loops, you can use fancy new for-loops instead!
As another answer said,
boost::zip_iteratoris your friend here, but it doesn’t have to be hard to use. Here’s a solution using a range adaptor that is implemented withzip_iteratorThat zip function creates an adaptor with
begin()andend()members that return aboost::zip_iterator, so the loop variable is a tuple of the elements of each underlying container (and as it’s a variadic template you can do it for any number of containers, so you don’t need to writefor_each_for_three_rangesandfor_each_for_four_rangesetc.)You could also use it with
for_each