2010-07-23 18 views
5

Tengo un problema poniendo los datos en un unordered_map usando una estructura como la clave:estructura como la clave de 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; 

Mi problema es que la función hash devuelve el mismo valor para osdpi_flow_identificators que tienen el mismo valor, pero


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()) { 
    ... 

no lo encuentra, aunque una entrada con un flow_id que tiene exactamente los mismos valores, ya está en el mapa hash. Lo verifiqué, al generar el mapa hash completo y también la función hash imprime el mismo valor. Por lo tanto, es bastante difícil para mí entender por qué unordered_map no puede encontrar la entrada con el mismo hash.

También intenté sobrecargar el operador == y el operador <, que a veces encontré como una sugerencia en la red, pero esas funciones tampoco fueron llamadas.

Lo que soluciona el problema, pero, por supuesto, más tarde termina con un error de segmentación, es dejar flow_id sin inicializar, entonces la entrada se puede encontrar correctamente.

¡Se agradece cualquier ayuda!

Gracias Steffen

+1

Esto es obviamente incorrecto: typedef unordered_map osdpi_flows_hashmap; ¿Podría escribir los parámetros de plantilla correctos de unordered_map? – Scharron

+0

Gracias, Scharron. Lo siento ... menos/más grande que los letreros fueron despojados. Los reemplazó ahora con <y> – StephenKing

+0

FYI, primero, se llama a la función hash en su clave, luego si existen algunos objetos con el mismo hash, se llama operador ==. operador Scharron

Respuesta

1

Ok, finalmente me encontré :-)

De hecho es necesario definir un EqualOperator para su hachís, dado que está utilizando punteros. Debería ser algo como:

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

entonces su declaración HashMap se convierte en

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

Otra manera de hacerlo es almacenar objetos en el mapa hash, en lugar de punteros. Depende si realmente quieres punteros en él.

+0

Sí, genial ... hice mi día/semana :) Tuve que declarar la función operator() como const: bool operator() (...) const {..}, de lo contrario, falló con: "error: passing" const osdpi_flow_equal 'como' este 'argumento de' bool osdpi_flow_equal :: operator() (osdpi_flow_identificador *, osdpi_flow_identificador *) 'descarta calificadores'. ¡Gracias! – StephenKing

+0

¿No podría usar el operador incorporado? Algo como 'return * id1 == * id2;'. –

+0

@StephenKing: tienes razón, lo edité. – Scharron

Cuestiones relacionadas