BOOST_FOREACH & templates without typedef

When I work with BOOST_FOREACH, there is no problem with simple patterns as a vector. But when I try to iterate through map> for example, I need a typedef element type.

Is there any workaround?

+10
c ++ boost
Nov 11 '09 at 7:40
source share
4 answers

There is a problem because it is a macro and therefore cannot process types containing commas (the preprocessor does not know about patterns).

You can also declare a variable before the loop, see the 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:

In particular, there is another complication of std::map : value_type not std::pair<Key, Value> , but std::pair<const Key, Value> .

Therefore, if you go with typedef, the more correct way (and the only way if you want to use the link in a 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, this will not work if you want to use the variable declared before the loop, since you cannot assign an instance of std::pair<const int, double> later (you cannot assign a const to the field), in which case you can use pair<int, double> only as indications of manual control.

+12
Nov 11 '09 at 7:54
source share
— -

If you need to iterate over a map, the easiest way is to use tuples, since getting the right type for typedef is unpleasant. Here's how you can use tuples:

 std::map<int, double> my_map; int key; double value; BOOST_FOREACH(boost::tie(key, value), my_map) { ... } 

Just a note, commas will work here because the brackets are located around the key and value. The preprocessor only understands commas and brackets (and c99 requires it to also understand quotes). Thus, it cannot parse <> into std::pair<int, double> . However, we can use parentheses to help the preprocessor. For example, if we have a function that returns a container that is called like this:

 BOOST_FOREACH(int i, foo<int, int>()) { ... } //This won't compile 

So, we can put brackets around the expression, and this will help the preprocessor:

 BOOST_FOREACH(int i, (foo<int, int>())) { ... } //This will compile 

However, in the case of the map, we cannot put brackets around the declaration (because it is not an expression). So this will not work:

 BOOST_FOREACH((std::pair<int, double> p), my_map) { ... } //This won't work 

Because it is converted to something like (std::pair<int, double> p) = *it , and this, of course, is not true in C ++. But using a tie will work:

 BOOST_FOREACH(tie(key, value), my_map) { ... } //This will work 

We just need to declare the key and value outside the loop (as shown above). In addition, it can make the cycle more meaningful. You can write key instead of p.first and value instead of p.second .

+8
Jan 14 2018-12-12T00
source share
+6
Nov 17 '09 at 0:19
source share

It could be that simple:

 BOOST_FOREACH(auto& p, my_map) { ... } 

Using the C ++ 11 standard, auto is like var in C #, it will do

 BOOST_FOREACH(std::pair<int, double>& p, my_map) { ... } 
+2
Feb 03 '13 at 3:25
source share



All Articles