2011-10-24 28 views
15

In C++, sto usando la trasformazione per modificare tutti i valori di una mappa in maiuscolo.Come applicare una trasformazione a una mappa STL in 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); 
     }); 

Questo mi dà il seguente errore di compilazione:

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

Penso che ci sia qualcosa che non va con il tipo dell'argomento nella mia espressione lambda. Probabilmente è qualcosa di semplice, ma non riesco a capire cosa ci si aspetta.

+3

Anziché presupporre che un contenitore memorizzi un tipo particolare. È possibile accedere alle informazioni sul tipo tramite value_type. 'std :: map :: value_type' –

+0

grazie, sto ancora imparando gli idiomi C++ ... – daj

risposta

19

Manca il const nel primo tipo della coppia.

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

Tuttavia questo non è il vostro problema: non è possibile utilizzare un map come OutputIterator, in quanto non supportano l'assegnazione. È possibile, tuttavia, modificare il secondo argomento utilizzando std::for_each.

buona vecchia map_to_foobar:

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

concettuale roba: Chiamare transform con la stessa gamma di input e output è abbastanza legittime e fa un sacco di senso se tutti i funtori ritornano per valore e non mutano la loro argomenti. Tuttavia, la modifica di qualcosa sul posto può essere più veloce (o almeno sembrare più veloce nel codice, non curare il compilatore di ottimizzazione) e ha molto senso con le funzioni dei membri.

+0

Aggiungere un const mi dà un altro errore/opt/local/include/gcc46/C++/bits/stl_pair.h: 156: 2: errore: passando 'const std :: basic_string ' come 'questo' argomento di '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 ] 'ignards qualifiers [-fpermissive] – daj

+0

@daj Scusa, mi sono reso conto fino a tardi. La modifica lo spiega. – pmr

+2

In alternativa, puoi usare 'std :: transform' con un iteratore di trasformazione. Ad esempio, il mio 'key_iterator', pubblicato in [una risposta ad un'altra domanda] (http://stackoverflow.com/questions/2467000/is-there-a-java-map-keyset-equivalent-for-cs-stdmap/ 5099345 # 5099345), può essere banalmente convertito in un 'value_iterator'. Quindi si finirebbe con 'std :: transform (begin_values ​​(data), end_values ​​(data), begin_values ​​(data), [] (std :: string s) {boost :: to_upper (s); return s;}); '. In questo caso, suggerirei comunque 'std :: for_each', perché elimina la copia non necessaria. –

Problemi correlati