Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using BOOST_FOREACH with std::map

I'd like to iterate over a std::map using BOOST_FOREACH and edit the values. I can't quite get it.

typedef std::pair<int, int> IdSizePair_t;
std::map<int,int> mmap;    
mmap[1] = 1;
mmap[2] = 2;
mmap[3] = 3;
BOOST_FOREACH( IdSizePair_t i, mmap )
    i.second++;
// mmap should contain {2,3,4} here

Of course this doesn't change anything because I'm not iterating by reference. So I substitute this line instead (as per the example in the Boost docs):

BOOST_FOREACH( IdSizePair_t &i, mmap )

and I get the compiler error:

error C2440: 'initializing' : 
cannot convert from 'std::pair<_Ty1,_Ty2>' to 'IdSizePair_t &'
    with
    [
        _Ty1=const int,
        _Ty2=int
    ]

Any suggestions?

like image 568
kmote Avatar asked Apr 27 '09 21:04

kmote


3 Answers

The problem is with the first member of the pair, which should be const. Try this:

typedef std::map<int, int> map_t;
map_t mmap;  
BOOST_FOREACH( map_t::value_type &i, mmap )
    i.second++;
like image 66
hvintus Avatar answered Oct 11 '22 06:10

hvintus


This is an old thread, but there is a more convenient solution.

boost has the notion of 'range adapters' that perform a transformation on iterator ranges. There are specific range adapters for this exact use case (iterating over map keys or values): boost::adaptors::map_values and boost::adaptors::map_keys.

So you could iterate over map values like this:

BOOST_FOREACH(int& size, mmap | boost::adaptors::map_values)
{ 
    ++size;
}

More information here.

like image 44
Alex Goldberg Avatar answered Oct 11 '22 04:10

Alex Goldberg


Another option is to use BOOST_FOREACH_PAIR, see my answer here:

BOOST_FOREACH & templates without typedef

like image 31
dtw Avatar answered Oct 11 '22 05:10

dtw