Sto cercando un modo semplice per creare un iteratore per i valori di una map
in C++ 11.Iterator per C++ 11 valori della mappa (semplici e trasparenti)
Questo metodo dovrebbe essere semplice e trasparente: semplice, nel senso che dovrebbe essere facile da implementare, e trasparente che il cliente non deve conoscere i valori provengono da una mappa, non un set.
Questa domanda è stata posta diverse volte prima. Molte di queste domande precedono C++ 11 e usano boost, che non voglio usare. Alcuni non sono semplici, la soluzione di John Ahlgren qui, http://john-ahlgren.blogspot.com/2013/10/how-to-iterate-over-values-of-stdmap.html, ad esempio, richiede una pagina di codice per scrivere un iteratore personalizzato.
Gli altri non sono trasparenti, vale a dire, chiaramente si può scrivere:
map<string,foo> mymap;
for (auto it=mymap.begin();it!=mymap.end();++it){
Foo val= it->second;
...
}
Tuttavia, non voglio fare questo perché non voglio il cliente di avere a sapere della rappresentazione dei dati.
Il problema si presenta come segue.
Ho un sacco di oggetti indicizzati in modo unico con una "chiave" a lungo. A volte voglio manipolare serie di questi oggetti. Altre volte voglio recuperare un oggetto data la sua chiave.
Non riesco a utilizzare la classe "set" direttamente per diversi motivi, il principale tra i quali è che non memorizza istanze mutabili e queste istanze devono essere modificabili (tranne, ovviamente, per la chiave).
Così, ho deciso di archiviare tutti i miei oggetti in una tabella hash globale gigante:
map<long,Foo> all_the_objects;
Ho poi non lavoro con set<Foo>
a tutti. Invece io lavoro con set<long>
e utilizzare un adattatore per simulare una serie di Foo, vale a dire,
class SetOfFoo{
private: set<long> theKeys;
public:
void insert(const & Foo);
size_t size() return theKeys.size();
bool is_member(const & Foo)
{return theKeys.find(Foo.key)
!= theKeys.end;}
Foo & insert(const & Foo val){
long key=val.key;
all_the_objects[key]=val;
return all_the_objects[key];
}
...::iterator begin() {???}
}
In altre parole, il cliente della classe SetOfFoo non conosce o non ha bisogno di sapere che SetOfFoo è implementato come come insieme di chiavi.
Non riesco neanche a creare un vettore nella classe dell'adattatore, perché non è possibile memorizzare riferimenti in raccolte C++.
È davvero impossibile creare un modo semplice e trasparente per iterare sulla mappa valori <>? Lo trovo difficile da credere, poiché questo è un bisogno molto comune ed è banale da fare in tutte le lingue che ho visto con hashtables. Non capisco come possa essere difficile.
Se fossi facendo questo mi piacerebbe usare 'per (auto const & valore: mymap | boost :: adattatori :: map_values) {/*...*/ } '. Questo utilizza [boost :: adapters :: map_values] (http://www.boost.org/doc/libs/1_55_0/libs/range/doc/html/range/reference/adaptors/reference/map_values.html) da Boost.Range'. – Mankarse
Nota a margine: 'std :: map' utilizza una rappresentazione ad albero, ** non ** una tabella hash. Se hai veramente bisogno della ricerca O (1), usa un 'std :: unordered_map'. –
Non voglio usare Boost. Ho pensato che la STL abbia soppiantato Boost, comunque, ho già molte cose enormi in questo codice, ho più che sufficiente difficoltà a compilarlo e collegarlo così com'è. Non ho intenzione di aggiungere una libreria completamente nuova per alcune cose banali come questa! – kdog