2010-07-23 11 views
5

Ho un problema di mettere i dati in un unordered_map utilizzando una struct come chiave:struct come chiave di unordered_map


typedef struct osdpi_flow_identificator { 
u32 lower_ip; 
u32 upper_ip; 
u16 lower_port; 
u16 upper_port; 
u8 protocol; 
} osdpi_flow_identificator_t; 

// custom hash function for osdpi_flow_identificator 
struct osdpi_flow_hash { 
std::size_t operator() (osdpi_flow_identificator * key) const { 
    hash hash_function; 
    std::size_t returnValue = 
    hash_function(key->lower_ip) 
    + hash_function(key->upper_ip) 
    + hash_function(key->lower_port) 
    + hash_function(key->upper_port) 
    + hash_function(key->protocol); 

    printf(" calculated hash: %i\n", returnValue); 

    return returnValue; 
} 
}; 

typedef unordered_map <osdpi_flow_identificator*, osdpi_flow*, osdpi_flow_hash> osdpi_flows_hashmap; 
typedef osdpi_flows_hashmap::value_type osdpi_flows_pair; 
static osdpi_flows_hashmap osdpi_flows; 

Il mio problema è che la funzione di hash restituisce lo stesso valore per osdpi_flow_identificators aventi lo stesso valore, ma


osdpi_flow_identificator * flow_id = new osdpi_flow_identificator; 
osdpi_flows_hashmap::const_iterator iter; 
iter = osdpi_flows.find(flow_id); 
if (iter != osdpi_flows.end()) { 
    ... 

non lo trova, sebbene una voce con un flow_id che abbia esattamente gli stessi valori sia già nella mappa di hash. L'ho verificato, emettendo l'intera mappa di hash e anche la funzione di hash stampa lo stesso valore. Quindi è abbastanza difficile per me capire, perché unordered_map non riesce a trovare la voce con lo stesso hash.

Ho anche provato a sovraccaricare l'operatore == e l'operatore <, che a volte ho trovato come suggerimento nella rete, ma anche quelle funzioni non sono state chiamate.

Ciò che risolve il problema, ma, naturalmente, in seguito si conclude con un errore di segmentazione, è quello di lasciare flow_id non inizializzato - quindi la voce può essere trovata correttamente.

Qualsiasi aiuto è apprezzato!

Grazie Steffen

+1

Questo è ovviamente sbagliato: typedef unordered_map osdpi_flows_hashmap; Potresti scrivere i parametri del modello giusto di unordered_map? – Scharron

+0

Grazie, Scharron. Scusa .. meno/maggiore rispetto ai segni sono stati spogliati. Ora li abbiamo sostituiti con <e> – StephenKing

+0

FYI, in primo luogo, viene chiamata la funzione di hash sulla chiave, quindi se alcuni oggetti esistono con lo stesso hash, viene chiamato l'operatore ==. L'operatore viene chiamato solo con std :: map (mappe ordinate). – Scharron

risposta

1

Ok, ho finalmente trovato :-)

In realtà è necessario definire un EqualOperator per il vostro hash, dal momento che si sta utilizzando puntatori. Dovrebbe essere qualcosa di simile:

struct Eq 
{ 
    bool operator() (osdpi_flow_identificator * id1, osdpi_flow_identificator * id2) const 
    { 
    id1->lower_ip == id2->lower_ip && // compare all fields. 
    } 
}; 

allora la vostra dichiarazione hashmap diventa

typedef unordered_map <osdpi_flow_identificator*, osdpi_flow*, osdpi_flow_hash, Eq> osdpi_flows_hashmap; 

Un altro modo per farlo è quello di memorizzare gli oggetti nel HashMap, invece di puntatori. Dipende se vuoi davvero dei suggerimenti.

+0

Sì, cool .. ha reso il mio giorno/settimana :) Ha dovuto dichiarare la funzione operator() come const: bool operator() (...) const {..}, altrimenti non è riuscita con: "error: passing" const osdpi_flow_equal 'as' this 'argomento di' bool osdpi_flow_equal :: operator() (osdpi_flow_identificator *, osdpi_flow_identificator *) 'scarta i qualificatori ". Grazie! – StephenKing

+0

Non potresti usare l'operatore integrato? Qualcosa come 'return * id1 == * id2;'. –

+0

@StephenKing: hai ragione, l'ho modificato. – Scharron

Problemi correlati