2012-05-01 15 views
9

Antecedentes: Estoy viniendo desde el mundo Java y yo soy bastante nuevo en C++ o Qt.C++ unordered_map fallar cuando se utiliza con un vector como clave

Para jugar con unordered_map, he escrito el siguiente programa simple:

#include <QtCore/QCoreApplication> 
#include <QtCore> 
#include <iostream> 
#include <stdio.h> 
#include <string> 
#include <unordered_map> 

using std::string; 
using std::cout; 
using std::endl; 
typedef std::vector<float> floatVector; 

int main(int argc, char *argv[]) { 
    QCoreApplication a(argc, argv); 

    floatVector c(10); 
    floatVector b(10); 

    for (int i = 0; i < 10; i++) { 
     c[i] = i + 1; 
     b[i] = i * 2; 
    } 

    std::unordered_map<floatVector, int> map; 

    map[b] = 135; 
    map[c] = 40; 
    map[c] = 32; 

    std::cout << "b -> " << map[b] << std::endl; 
    std::cout << "c -> " << map[c] << std::endl; 
    std::cout << "Contains? -> " << map.size() << std::endl; 

    return a.exec(); 
} 

Por desgracia, estoy corriendo en el error folowing que no es inspirador. Ni siquiera hay un número de línea.

:-1: error: collect2: ld returned 1 exit status

¿Alguna idea del origen del problema?

Gracias de antemano.

+1

Necesita una función hash que tome un 'vector ' –

+2

Esto no es un error en el tiempo de ejecución. –

+0

@SethCarnegie Eso fue lo que pensé que el problema también venía. Sin embargo, me parece que una clase tan básica como vector debe tener una función hash predeterminada. Si no es el caso, ¿podría explicarme cómo proporcionar uno o señalarme algún material? ¡Gracias! –

Respuesta

21

§23.2.5, párrafo 3, dice:

Each unordered associative container is parameterized by Key , by a function object type Hash that meets the Hash requirements (17.6.3.4) and acts as a hash function for argument values of type Key , and by a binary predicate Pred that induces an equivalence relation on values of type Key .

Usando vector<float> como Key y no proporcionar tipos de hash y predicado equivalencia explícitos significa el valor por defecto std::hash<vector<float>> y std::equal_to<vector<float>> se utilizará.

La relación de equivalencia std::equal_to está bien, porque hay un operador == para vectores, y eso es lo que usa std::equal_to.

Existe, sin embargo, no std::hash<vector<float>> especialización, y eso es probablemente lo que el error de vinculador que no mostró nos dice. Debe proporcionar su propio hasher para que esto funcione.

Una manera fácil de escribir un hasher tal es utilizar boost::hash_range:

template <typename Container> // we can make this generic for any container [1] 
struct container_hash { 
    std::size_t operator()(Container const& c) const { 
     return boost::hash_range(c.begin(), c.end()); 
    } 
}; 

continuación, puede utilizar:

std::unordered_map<floatVector, int, container_hash<floaVector>> map; 

Por supuesto, si usted necesita una semántica diferente de igualdad en el mapa que necesita para definir la relación hash y equivalencia apropiadamente.


1. Sin embargo, evitar esto para hashing recipientes no ordenados, ya que diferentes órdenes se producen diferentes valores hash, y el orden en el recipiente no ordenada no está garantizada.

+1

Muchas gracias, esto solucionó mi problema. Nota para las personas que tendrían el mismo problema: para usar boost :: hash_range necesitas #include

+0

@ user1162647: Eso es literalmente lo primero en esa página de documento. ; -] – ildjarn

+0

@R.Martinho Fernandes: Si todavía estás mirando, los documentos en esa página dicen: "hash_range es sensible al orden de los elementos por lo que no sería apropiado usar esto con un contenedor desordenado". ¿Eso sugiere que el uso anterior es incorrecto? – ForeverLearning

Cuestiones relacionadas