2011-10-24 20 views
15

En C++, estoy usando la transformación para cambiar todos los valores de un mapa a mayúsculas.Cómo aplicar la transformación a un mapa STL en C++

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); 
     }); 

Esto me da el siguiente error de compilación:

/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> >&) 

Creo que hay algo mal con el tipo del argumento en mi expresión lambda. Probablemente sea algo simple, pero parece que no puedo entender lo que se espera.

+3

En lugar de asumir que un contenedor almacena un tipo particular. Puede acceder a la información de tipo a través de value_type. 'std :: map :: value_type' –

+0

gracias, todavía estoy aprendiendo modismos en C++ ... – daj

Respuesta

19

Te estás perdiendo la const en el primer tipo del par.

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

Sin embargo esto no es su problema: No se puede utilizar un map como el OutputIterator, ya que no son compatibles con la asignación. Sin embargo, puede mutar el segundo argumento usando std::for_each.

El bueno de map_to_foobar:

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

conceptual cosas: Llamada transform con el mismo rango que la entrada y salida es muy de fiar y tiene mucho sentido si todos sus funtores regresan por su valor y no mutan su argumentos. Sin embargo, mutar algo en su lugar puede ser más rápido (o al menos parecer más rápido en el código, sin importar el compilador de optimización) y tiene mucho sentido con las funciones de los miembros.

+0

Añadiendo un const me da otro error/opt/local/include/gcc46/C++/bits/stl_pair.h: 156: 2: error: pasar 'const std :: basic_string ' como 'este' argumento de 'std :: basic_string <_CharT, _Traits, _Alloc> & std :: basic_string <_CharT, _Traits , _Alloc> :: operator = (const std :: basic_string <_CharT, _Traits, _Alloc> &) [con _CharT = char, _Traits = std :: char_traits , _Alloc = std :: allocator , std :: basic_string <_CharT , _Traits, _Alloc> = std :: basic_string ] 'descarta los calificadores [-permissive] – daj

+0

@daj Lo siento, me di cuenta hasta tarde. La edición lo explica. – pmr

+2

Alternativamente, puede usar 'std :: transform' con un iterador de transformación. Por ejemplo, mi 'key_iterator', publicado en [una respuesta a otra pregunta] (http://stackoverflow.com/questions/2467000/is-there-a-java-map-keyset-equivalent-for-cs-stdmap/ 5099345 # 5099345), se puede convertir trivialmente en un 'value_iterator'. Luego terminaría con 'std :: transform (begin_values ​​(data), end_values ​​(data), begin_values ​​(data), [] (std :: string s) {boost :: to_upper (s); return s;}); '. En este caso, sugeriría 'std :: for_each', sin embargo, porque elimina la copia innecesaria. –

Cuestiones relacionadas