std :: mapas con tipos definidos por el usuario como clave

Me pregunto por qué no puedo usar mapas STL con clases definidas por el usuario. Cuando compilo el código a continuación, aparece este mensaje de error críptico. Qué significa eso? Además, ¿por qué solo está sucediendo con tipos definidos por el usuario? (los tipos primitivos están bien cuando se usa para la clave)

C: \ MinGW \ bin .. \ lib \ gcc \ mingw32 \ 3.4.5 …….. \ include \ c ++ \ 3.4.5 \ bits \ stl_function.h || En la función miembro `bool std :: menos :: operator () (const _Tp &, const _Tp &) const [con _Tp = Class1] ‘: |

C: \ MinGW \ bin .. \ lib \ gcc \ mingw32 \ 3.4.5 …….. \ include \ c ++ \ 3.4.5 \ bits \ stl_map.h | 338 | instanciado de `_Tp & std :: map :: operator [] (const _Key &) [con _Key = Class1, _Tp = int, _Compare = std :: less, _Alloc = std :: allocator>] ‘|

C: \ Users \ Admin \ Documents \ dev \ sandbox \ sandbox \ sandbox.cpp | 24 | instanciado desde aquí |

C: \ MinGW \ bin .. \ lib \ gcc \ mingw32 \ 3.4.5 …….. \ include \ c ++ \ 3.4.5 \ bits \ stl_function.h | 227 | error: no coincide con el operador ‘ <'en' __x <__y '| || === Build finished: 1 errores, 0 advertencias === |

#include  #include  using namespace std; class Class1 { public: Class1(int id); private: int id; }; Class1::Class1(int id): id(id) {} int main() { Class1 c1(1); map c2int; c2int[c1] = 12; return 0; } 

No tiene que definir operator< para su clase, en realidad. También puede hacer una clase de objeto de función de comparación para él, y usar eso para especializar std::map . Para extender tu ejemplo:

 struct Class1Compare { bool operator() (const Class1& lhs, const Class1& rhs) const { return lhs.id < rhs.id; } }; std::map c2int; 

Sucede que el valor predeterminado para el tercer parámetro de plantilla de std::map es std::less , que se delegará en el operator< definido para su clase (y fallará si no hay ninguno). Pero a veces desea que los objetos se puedan usar como claves de mapa, pero en realidad no tiene ninguna semántica de comparación significativa , por lo que no quiere confundir a las personas al proporcionar operator< en su clase solo por eso. Si ese es el caso, puedes usar el truco anterior.

Otra forma de lograr lo mismo es especializar std::less :

 namespace std { template<> struct less { bool operator() (const Class1& lhs, const Class1& rhs) const { return lhs.id < rhs.id; } }; } 

La ventaja de esto es que será seleccionado por std::map "de manera predeterminada", y sin embargo, no expones al operator< al código del cliente de lo contrario.

Por defecto, std::map (y std::set ) usan operator< para determinar la clasificación. Por lo tanto, necesita definir operator< en su clase.

Dos objetos se consideran equivalentes if !(a < b) && !(b < a) .

Si, por alguna razón, desea utilizar un comparador diferente, el tercer argumento de la plantilla del map se puede cambiar, por ejemplo, a std::greater .

Debe definir operator < para Class1.

El mapa necesita comparar los valores utilizando el operador

 class Class1 { public: Class1(int id); bool operator <(const Class1& rhs) const { return id < rhs.id; } private: int id; }; 

Las claves deben ser comparables, pero no ha definido un operator< adecuado operator< para su clase personalizada.

 class key { int m_value; public: bool operator<(const key& src)const { return (this->m_value < src.m_value); } }; int main() { key key1; key key2; map mymap; mymap.insert(pair(key1,100)); mymap.insert(pair(key2,200)); map::iterator iter=mymap.begin(); for(;iter!=mymap.end();++iter) { cout<second< 

La solución correcta es Especializar std::less para su clase / Struct.

• Básicamente, los mapas en cpp se implementan como árboles de búsqueda binaria.

  1. Las BST comparan los elementos de los nodos para determinar la organización del árbol.
  2. Los nodos cuyos elementos se comparan menos que los del nodo padre se colocan a la izquierda del elemento primario y los nodos cuyos elementos se pueden comparar más que el elemento de los nodos principales se colocan a la derecha. es decir

Para cada nodo, node.left.key

Cada nodo en la BST contiene Elementos y en el caso de los mapas su LLAVE y un valor, y se supone que las teclas se ordenan. Más información sobre la implementación del mapa: el tipo de datos del mapa .

En el caso de los mapas cpp, las claves son los elementos de los nodos y los valores no forman parte de la organización del árbol, solo son datos complementarios.

Entonces, significa que las claves deben ser compatibles con std::less o operator< para que puedan organizarse. Por favor revisa los parámetros del mapa .

De lo contrario, si está utilizando el tipo de datos definido por el usuario como claves, entonces debe dar significado a la semántica de comparación completa para ese tipo de datos.

Solución : Especializar std::less :

El tercer parámetro en la plantilla del mapa es opcional y es std::less que delegará al operator< ,

Por lo tanto, cree un nuevo std::less para su tipo de datos definido por el usuario. Ahora std::map elegirá este nuevo estándar de forma predeterminada.

 namespace std { template<> struct less { bool operator() (const MyClass& lhs, const MyClass& rhs) const { return lhs.anyMemen < rhs.age; } }; } 

Nota: Debe crear std::less para cada tipo de datos definido por el usuario (si desea usar ese tipo de datos como clave para los mapas cpp).

Solución incorrecta: operator< sobrecarga operator< para su tipo de datos definido por el usuario. Esta solución también funcionará, pero es muy mala ya que el operador < estará sobrecargado universalmente para su tipo / clase de datos. que es indeseable en escenarios de clientes.

Por favor, compruebe la respuesta de Pavel Minaev