How can I iterate over two vectors simultaneously using BOOST_FOREACH?
Iterating over two things simultaneously is called a "zip" (from functional programming), and Boost has a zip iterator:
The zip iterator provides the ability to parallel-iterate over several
controlled sequences simultaneously. A zip iterator is constructed
from a tuple of iterators. Moving the zip iterator moves all the
iterators in parallel. Dereferencing the zip iterator returns a tuple
that contains the results of dereferencing the individual iterators.
Note that it's an iterator, not a range, so to use BOOST_FOREACH
you're going to have to stuff two of them into an iterator_range or pair
. So it won't be pretty, but with a bit of care you can probably come up with a simple zip_range
and write:
BOOST_FOREACH(boost::tuple<int,int> &p, zip_range(v1, v2)) {
doSomething(p.get<0>(), p.get<1>());
}
Or special-case for 2 and use std::pair
rather than boost::tuple
.
I suppose that since doSomething
might have parameters (int&, int&)
, actually we want a tuple<int&,int&>
. Hope it works.
BOOST_FOREACH and a vector
BOOST_FOREACH
behaves exactly as you tell him, by value, reference or const reference
C++11 for each loop with more than one variable
There is no built-in way to do this. If you can use Boost, boost::combine
will work for iterating two (or more) ranges simultaneously (Does boost offer make_zip_range?, How can I iterate over two vectors simultaneously using BOOST_FOREACH?):
for (boost::tuple<int&, int&> ij : boost::combine(a, b)) {
int& i = boost::get<0>(ij);
int& j = boost::get<1>(ij);
// ...
}
Unfortunately accessing the elements within the tuple elements of the zipped range is highly verbose. C++17 will make this much more readable using structured binding:
for (auto [&i, &j] : boost::combine(a, b)) {
// ...
}
Since you don't need to break out of the loop or return from the enclosing function, you could use boost::range::for_each
with the body of your loop as a lambda:
boost::range::for_each(a, b, [](int& i, int& j)
{
// ...
});
Redefine BOOST_FOREACH macro safely
You could use an inline helper function.
#define FOREACH(decl, c) BOOST_FOREACH(decl, pair_helper(c))
template <typename T>
inline std::pair<typename T::iterator, typename T::iterator> pair_helper (T c) {
return std::make_pair(c.begin(), c.end());
}
BOOST_FOREACH & templates without typedef
There is a problem because it is a macro, and therefore cannot handle types containing commas (preprocessor doesn't know about templates).
You can also declare the variable before the loop, see documentation.
std::map<int, double> my_map;
//1)
typedef std::pair<int, double> MyPair;
BOOST_FOREACH(MyPair p, my_map) { ... }
//2)
std::pair<int, double> p;
BOOST_FOREACH(p, my_map) { ... }
Edit:
There is a further complication with std::map
in particular: the value_type
is not std::pair<Key, Value>
, but std::pair<const Key, Value>
.
Hence, if you go with the typedef, a more proper way (and the only way if you want to use a reference in the foreach loop) is to use
typedef std::pair<const int, double> MyPair;
//or
typedef std::map<int, double>::value_type MyPair;
BOOST_FOREACH(MyPair& ref, my_map) { ... }
However, that won't work if you want to use a variable declared before the loop, since you can't assign to a std::pair<const int, double>
instance later (can't assign to the const field), in which case you can only use pair<int, double>
as boost's manual shows.
Related Topics
C++ 2 Dimensional Array with Variable Size Rows
C++ "Hello World" Boost Tee Example Program
Can You Start a Class Name with a Numeric Digit
With C++, I Get Pointer with 0Xcdcdcdcd When Creating a Class - What Is Happening
Can a Copy-Constructor Take a Non-Const Parameter
Should "Delete This" Be Called from Within a Member Method
C++: Function Pointer to Functions with Variable Number of Arguments
C++ Class Member Function Callback
Best Way to for C++ Types to Self Register in a List
Insert into an Stl Queue Using Std::Copy
Why Does 'Std::Basic_Ifstream<Char16_T>' Not Work in C++11
Boost.Python: Wrap Functions to Release the Gil
Class' Keyword in Variable Definition in C++
Visual Studio Debugger Error: Unable to Start Program Specified File Cannot Be Found
What Is the Meaning of 'Struct X Typedef' VS. 'Typedef Struct X'