2012-12-18 11 views
5

È possibile modificare il metodo di confronto di una std :: map dopo che è stata creata e inizializzata? O forse solo dopo che è stato creato ??std :: cambio di mappa key_comp dopo l'inizializzazione

Voglio modificare in qualche modo il comportamento di una classe che contiene una mappa che non posso modificare la definizione. Voglio cambiare il comportamento di confronto, magari passando un'altra mappa.

+0

Vedete una funzione qui per consentirvi di farlo direttamente: http://en.cppreference.com/w/cpp/container/map? In caso contrario, la risposta è no ... – Nim

+2

È un parametro template, quindi deve essere corretto in fase di compilazione. Modificarlo cambierebbe il tipo del contenitore. – v154c1

risposta

4

forse è possibile, questo non è testato:

  1. Definire il proprio comparatore personalizzato, che ha al suo interno un puntatore alla reale attuazione della funzione di confronto
  2. passare un'istanza di questo al costruttore la mappa (devi digitare la mappa usando anche questo comparatore.)
  3. Imposta l'implementazione reale in un secondo momento (prima di utilizzare la mappa), se la imposta dopo, non conosci l'impatto sugli interni ...

hanno testato, ed è possibile fare quanto sopra, ma cambiando la funzione di confronto se ci sono elementi nella struttura possono essere disastrose ...

In ogni caso - tutto sembra troppo pesce ....

+0

Va bene. La mappa è vuota – djWann

+0

@djWann Penserei che il sovraccarico delle chiamate confronta ogni volta tramite un puntatore a funzione rallenta in modo significativo le operazioni di 'map', se ci tieni. – rici

+0

@djWann Se la mappa è vuota, perché non usarne una nuova? O due oggetti completamente diversi o purché il comparatore sia la stessa firma: 'my_map = std :: map <...> (& new_compare);' – rioki

1

Non è possibile. Ma puoi creare una nuova mappa, con i criteri di confronto alternativi, e il costruttore di due iteratori per istanziare la mappa usando gli elementi del primo.

bool C1(const K&, const K&); 
bool C2(const K&, const K&); 

std::map<K, V, C1> orig; 
.... 
std::map<K, V, C2> alternative(orig.begin(), orig.end()); 
1

No, non è possibile, dal momento che è compilato nella mappa tramite un argomento di template.

Vedi: http://www.cplusplus.com/reference/map/map/Confronta è quello che stai cercando.

Che cosa stai cercando di fare?

Poiché si ha la classe nella mano che si utilizza come chiave, è possibile implementare l'operatore < o la funzione di confronto per reagire al contesto. Poiché è possibile passare un oggetto completamente costruito allo constructor come funzione di confronto, dovrebbe essere possibile passare tutto insieme per implementare una compassione dipendente dal contesto. La domanda è, perché vorresti?

È una cattiva idea per modificare il confronto di std :: map mentre è in esecuzione, in quanto causerà un comportamento non definito. Semplicemente basato sul fatto che il contenuto di std :: map è "ordinato" (probabilmente un albero RB). Se cambi la funzione di ordinamento cambierai improvvisamente l'ordine logico; ma la mappa non si riordina magicamente da sola. La prossima chiamata per inserire o trovare probabilmente non farà ciò che ti aspetti.

2

No, non è possibile. Il comparatore fa parte del tipo della mappa. La domanda non è diversa dal chiedere se è possibile modificare uno int per memorizzare numeri in virgola mobile.

Ancora più importante, l'ordine fornito dal comparatore è parte integrante della struttura interna della mappa. Se si dovesse modificare l'ordine, la struttura dei dati non sarebbe più in uno stato coerente.L'unica opzione fattibile è quella di ricostruire una nuova mappa da elementi del vecchio mappa rispetto al nuovo ordine, ma questo è già possibile:

std::map<T, V, Comp1> m1 = /* ... */; 
std::map<T, V, Comp2> m2(m1.begin(), m1.end()); 

In alternativa, è possibile effettuare una seconda mappa di tipo std::map<std::reference_wrapper<T const>, std::reference_wrapper<V>, Comp2> e popolarlo con riferimenti alla mappa originale, ma ordinati in base a Comp2. In tal caso è responsabilità dell'utente mantenere sincronizzate le due mappe. Un contenitore avanzato come Boost.Multiindex può farlo per te in modo sicuro.

Problemi correlati