tipos - typedef en c++ para que sirve
std:: mapas con tipos definidos por el usuario como clave (5)
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 <_Tp> :: 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 <_Key, _Tp, _Compare, _Alloc> :: 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 <iostream>
#include <map>
using namespace std;
class Class1
{
public:
Class1(int id);
private:
int id;
};
Class1::Class1(int id): id(id)
{}
int main()
{
Class1 c1(1);
map< Class1 , int> c2int;
c2int[c1] = 12;
return 0;
}
Debe definir operator <
para Class1.
El mapa necesita comparar los valores utilizando el operador <y, por lo tanto, debe proporcionar el mismo valor cuando la clase definida por el usuario se utiliza como clave.
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.
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<Class1, int, Class1Compare> 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<Class1>
{
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 std::map 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
.
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<key,int> mymap;
mymap.insert(pair<key,int>(key1,100));
mymap.insert(pair<key,int>(key2,200));
map<key,int>::iterator iter=mymap.begin();
for(;iter!=mymap.end();++iter)
{
cout<<iter->second<<endl;
}
}