2009-04-27 2 views
44

Я бы хотел перебрать std :: map с помощью BOOST_FOREACH и отредактировать значения. Я не могу это получить.с использованием BOOST_FOREACH с std :: map

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 

Конечно, это ничего не меняет, потому что я не повторяю ссылки. Поэтому я заменить эту строку вместо того, чтобы (как в примере в буста документации):

BOOST_FOREACH(IdSizePair_t &i, mmap) 

и я получаю ошибку компиляции:

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

Любые предложения?

+0

Какой компилятор вы используете? Я пробовал ваш код на VS2008, и он работал правильно. Я протестировал hvint [ответ] (http://stackoverflow.com/questions/795443/using-boostforeach-with-stdmap/795482#795482), и он сработал. Я использую boost 1.36, если это имеет значение. –

+0

вы, вероятно, забыли &? без этого, он копирует другую пару, и в дальнейшем это будет иметь значение. –

ответ

66

Проблема заключается в первом члене пары, который должен быть const. Попробуйте это:

typedef std::map<int, int> map_t; 
map_t mmap; 
BOOST_FOREACH(map_t::value_type &i, mmap) 
    i.second++; 
+0

+1. вы избили меня на несколько секунд: D –

+0

Спасибо, hvint. Так оно и было. Также (после прочтения вашего комментария) я понял, что другой способ исправить это - изменить первую строку моего исходного кода на это: typedef std :: pair IdSizePair_ty; (что позволяет мне перебирать по ссылке) – kmote

+0

kmote, да, на самом деле это то, что я предложил в своем ответе (который я удалил, когда увидел hvint). Кроме того, вы знаете, почему он ведет себя таким образом? Я буду восстанавливать мои, если вам нужно какое-то объяснение. –

4

Другой вариант заключается в использовании BOOST_FOREACH_PAIR см мой ответ здесь:

BOOST_FOREACH & templates without typedef

+1

Мне нравится внешний вид BOOST_FOREACH_PAIR, но я не вижу никаких официальных ссылок на него, и это не в версии 1.46, которую я использую.Он когда-либо включался в официальный релиз? –

+0

Это был просто домашний макрос - он никогда не реализовывался в boost. Завершено как wontfix (в пользу циклов на основе диапазона C++ 11) в https://svn.boost.org/trac/boost/ticket/3469 – baderous

21

Это старая нить, но есть более удобное решение.

boost имеет понятие «адаптеры диапазона», которые выполняют преобразование на диапазонах итераторов. Для этого конкретного варианта использования существуют специальные адаптеры диапазона (итерация по картам или значениям): boost::adaptors::map_values и boost::adaptors::map_keys.

Таким образом, вы можете перебрать значения карты, как это:

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

here Больше информации.

+0

Для этого решения ' 'необходимо включить. – scai

0

На C++ 11 рассмотреть возможность использования автоматического ключевого слова:

std::map<int,int> mmap;  
mmap[1] = 1; 
mmap[2] = 2; 
mmap[3] = 3; 

BOOST_FOREACH(auto& mpair, mmap) 
    mpair.second++; 

//mmap will contain {2,3,4} here 
Смежные вопросы