I have a 'foreach' macro I use frequently in C++ that works for most STL containers:
#define foreach(var, container) \
for(typeof((container).begin()) var = (container).begin(); \
var != (container).end(); \
++var)
(Note that 'typeof' is a gcc extension.) It is used like this:
std::vector< Blorgus > blorgi = ...;
foreach(blorgus, blorgi) {
blorgus->draw();
}
I would like to make something similar that iterates over a map's values. Call it "foreach_value", perhaps. So instead of writing
foreach(pair, mymap) {
pair->second->foo();
}
I would write
foreach_value(v, mymap) {
v.foo();
}
I can't come up with a macro that will do this, because it requires declaring two variables: the iterator and the value variable ('v', above). I don't know how to do that in the initializer of a for loop, even using gcc extensions. I could declare it just before the foreach_value call, but then it will conflict with other instances of the foreach_value macro in the same scope. If I could suffix the current line number to the iterator variable name, it would work, but I don't know how to do that.
You would be looking for BOOST_FOREACH - they have done all the work for you already!
If you do want to roll your own, you can declare a block anywhere in C++, which resolves your scope issue with your intermediate storage of itr->second ...
// Valid C++ code (which does nothing useful)
{
int a = 21; // Which could be storage of your value type
}
// a out of scope here
{
int a = 32; // Does not conflict with a above
}
You can do this using two loops. The first declares the iterator, with a name which is a function of the container variable (and you can make this uglier if you're worried about conflicts with your own code). The second declares the value variable.
#define ci(container) container ## iter
#define foreach_value(var, container) \
for (typeof((container).begin()) ci(container) = container.begin(); \
ci(container) != container.end(); ) \
for (typeof(ci(container)->second)* var = &ci(container)->second; \
ci(container) != container.end(); \
(++ci(container) != container.end()) ? \
(var = &ci(container)->second) : var)
By using the same loop termination condition, the outer loop only happens once (and if you're lucky, gets optimized away). Also, you avoid calling ->second on the iterator if the map is empty. That's the same reason for the ternary operator in the increment of the inner loop; at the end, we just leave var at the last value, since it won't be referenced again.
You could inline ci(container), but I think it makes the macro more readable.
The STL transform function also does something similar.
The arguments are (in order):
For a very simple example, you could capitalize each character in a string by:
#include <iostream>
#include <string>
#include <algorithm>
#include <cctype>
int main(int argc, char* argv[]) {
std::string s("my lowercase string");
std::transform(s.begin(), s.end(), s.begin(), toupper);
std::cout << s << std::endl; // "MY LOWERCASE STRING"
}
Alternatively there is also the accumulate function, which allows some values to be retained between calls to the function object. accumulate does not modify the data in the input container as is the case with transform.
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