2011-04-28 9 views
6

Tengo una estructura que tiene una clave única. Quiero insertar instancias de estas estructuras en un conjunto. Sé que para hacer esto, el operador < tiene que estar sobrecargado para que el conjunto pueda hacer una comparación para hacer la inserción.Cómo tener un conjunto de estructuras en C++

El siguiente no funciona:

#include <iostream> 
#include <set> 
using namespace std; 
struct foo 
{ 
     int key; 
}; 

bool operator<(const foo& lhs, const foo& rhs) 
{ 
     return lhs.key < rhs.key; 
} 

set<foo> bar; 

int main() 
{ 
    foo *test = new foo; 
    test->key = 0; 
    bar.insert(test); 
} 
+6

test.cpp: 20: error: no existe función de emparejamiento de llamada a 'std :: set , std :: asignador > :: insert (foo * &) ' El error me parece bastante claro. Estás intentando poner un puntero donde debería estar un objeto. – dcousens

+0

Ser capaz de editar una pregunta es agradable, pero no debe cambiar su significado al hacerlo. Esto invalida cualquier respuesta (posiblemente correcta) y obliga a los futuros lectores a mirar primero la edición. No hay ninguna limitación en StackOverflow con respecto a una misma persona que publique varias preguntas dentro de un corto período de tiempo. En realidad, eso es incluso una buena idea. – ereOn

Respuesta

10

Esto podría ayudar:

struct foo 
{ 
    int key; 
}; 

inline bool operator<(const foo& lhs, const foo& rhs) 
{ 
    return lhs.key < rhs.key; 
} 

Si está utilizando espacios de nombres, es una buena práctica para declarar la función operator<() en el mismo espacio de nombres.


En aras de la exhaustividad después de su edición, y como otros han señalado, que está intentando añadir un foo* donde se espera una foo.

Si realmente desea tratar con punteros, puede ajustar el foo* en una clase de puntero inteligente (auto_ptr, shared_ptr, ...).

Pero tenga en cuenta que en ambos casos, pierde el beneficio de la operator< sobrecargada que opera en foo, no en foo*.

+0

Eso funciona, pero no cuando se inserta en un conjunto. Cambié mi pregunta para incluir el código. –

+3

Responde a la pregunta original, sugiero que se elija como correcta, la pregunta adaptada fue simplemente un error de sintaxis. – dcousens

+0

Me encantó el hecho de que haya utilizado la palabra clave ['inline'] (http://www.cprogramming.com/tutorial/lesson13.html) en sus funciones, ¡lo que aumenta el rendimiento! +1 –

3
struct Blah 
{ 
    int x; 
}; 

bool operator<(const Blah &a, const Blah &b) 
{ 
    return a.x < b.x; 
} 

... 

std::set<Blah> my_set; 

Sin embargo, no me gusta la sobrecarga operator< menos que hace sentido intuitivo (¿realmente tiene sentido decir que uno Blah es "menor que" otra Blah?). Si no es así, por lo general proporcionan una función personalizada en lugar comparador:

bool compareBlahs(const Blah &a, const Blah &b) 
{ 
    return a.x < b.x; 
} 

... 

std::set<Blah,compareBlahs> my_set; 
2

ver la respuesta de Ereon, que está bien.

El verdadero problema en que este código es:

foo *test = new foo; 
test->key = 0; 
bar.insert(test); 

inserta un punteroen el conjunto, no una estructura. Cambiar el insert a:

bar.insert(*test); 
//  ^

EDIT: pero entonces tendrá que delete foo, ya que se copiará en el set. O simplemente crear en la pila (usando set con punteros no es una buena idea, porque la disposición será "extraña" - el set clasificará de acuerdo a las direcciones de los punteros)

2

Puede sobrecargar el operator < dentro de la clase como también,

struct foo 
{ 
    int key; 
    bool operator < (const foo &other) const { return key < other.key; } 
}; 

En su pregunta, si desea utilizar set<foo> bar; como la declaración a continuación, se debe insertar un valor que,

bar.insert(*test); 

Pero eso no va a ser una buena idea, como yo Estás haciendo una copia redundante.

+0

>.> En realidad no funciona para std :: unordered_set though. – Dmitry

2

Lo mejor que puede hacer es dar un constructor foo:

struct foo 
{ 
    foo(int k) : key(k) { } 
    int key; 
}; 

A continuación, a añadir, en lugar de ...

foo *test = new foo; 
test->key = 0; 
bar.insert(test); // BROKEN - need to dereference ala *test 
// WARNING: need to delete foo sometime... 

... puede simplemente usar:

bar.insert(foo(0)); 
1

El problema no está en su conjunto; está en tu objeto test. Estás usando el estilo Java allí. En C++, sólo escribimos:

set<foo> bar; 

int main() 
{ 
    foo test; // Local variable, goes out of scope at } 
    test.key = 0; 
    bar.insert(test); // Insert _a copy of test_ in bar. 
}