Как применить преобразование к карте STL в С++

В С++ я использую transform для изменения всех значений карты в верхнем регистре.

  std::map<std::string, std::string> data = getData();

  // make all values uppercase
  std::transform(data.begin(), data.end(), data.begin(),
         [](std::pair<std::string, std::string>& p) {
           boost::to_upper(p.second);
           return(p);
         });

Это дает мне следующую ошибку компиляции:

/opt/local/include/gcc46/c++/bits/stl_algo.h:4805:2: error: no match for call to '(main(int, char**)::<lambda(std::pair<std::basic_string<char>, std::basic_string<char> >&)>) (std::pair<const std::basic_string<char>, std::basic_string<char> >&)

Я думаю, что что-то не так с типом аргумента в моем выражении лямбда. Это, наверное, что-то простое, но я не могу понять, что ожидается.

Ответы

Ответ 1

Вам не хватает const в первом типе пары.

[](std::pair<const std::string, std::string>& p) {

Однако это не ваша проблема: вы не можете использовать map в качестве OutputIterator, так как они не поддерживают назначение. Вы можете, однако, изменить второй аргумент, используя std::for_each.

Старый добрый map_to_foobar:

std::for_each(data.begin(), data.end(), 
              [](std::pair<const std::string, std::string>& p) {
                p.second = "foobar";
              });

Концептуальные вещи: вызов transform с тем же диапазоном, что и вход и выход, вполне закончен и имеет большой смысл, если все ваши функторы возвращаются по значению и не мутируют их аргументы. Тем не менее, мутация чего-то на месте может быть более быстрой (или, по крайней мере, выглядеть быстрее в коде, неважно оптимизирующий компилятор) и имеет большой смысл с функциями-членами.