I need a piece of advice for the following situation - I can't figure it out for hours: How to walk through more than one seq . containers of same size (here: two vectors) in a simple way?
int main() {
int size = 3;
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
// old-fashioned - ok
for (int i = 0; i < size; i++) {
std::cout << v1[i] << " " << v2[i] << std::endl;
}
// would like to do the same as above with auto range-for loop
// something like this - which would be fine for ONE vector.
// But this does not work. Do I need a hand-made iterator instead?
for (const auto& i:v1,v2) {
std::cout << i << " " << i << std::endl;
}
return EXIT_SUCCESS;
}
Thank you!
There is boost::combine()
in Boost.Range
that allows one to write
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/combine.hpp>
int main()
{
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
for (auto&& t : boost::combine(v1, v2))
std::cout << t.get<0>() << " " << t.get<1>() << "\n";
}
Live Example.
If you don't like to rely on this, you can spell out the combine()
functionality yourself with Boost.Iterator's zip_iterator
and Boost.Range's iterator_range
and a little bit of C++14 deduced return-types:
template<class... Ranges>
auto combine(Ranges const&... ranges)
// add -> decltype( boost::make_iterator_range(...) ) in C++11
{
return boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)),
boost::make_zip_iterator(boost::make_tuple(end(ranges)...))
);
}
Live Example.
Explanation: boost::make_zip_iterator
creates a boost::tuple
of iterators into your input ranges, and overloads all the usual operator++
and operator*
that you know and love from regular iterators. The iterator_range
then wraps two of these zip_iterator
s into a package with a begin()
and end()
function that allows it to be used by the C++11 range-for loop. It generalizes to more than two input ranges as well. You can unpack the K
-th element from a tuple with the .get<K>
member function.
The range-based for
loop was designed as a convenience for iterating one range, because it's by far the most common case. If you need to iterate multiple ranges, which is not that most common case, you can still do it the traditional way:
for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2)
{
// processing
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With