2010-04-15 16 views
9

Tengo un pequeño programa que desea ejecutar para probar algoProblema con std :: mapa y std :: par

#include <map> 
#include <iostream> 
using namespace std; 

struct _pos{ 
     float xi; 
     float xf; 

     bool operator<(_pos& other){ 

       return this->xi < other.xi; 
     } 
}; 

struct _val{ 

     float f; 
}; 

int main() 
{ 
     map<_pos,_val> m; 

     struct _pos k1 = {0,10}; 
     struct _pos k2 = {10,15}; 

     struct _val v1 = {5.5}; 
     struct _val v2 = {12.3};                 

     m.insert(std::pair<_pos,_val>(k1,v1)); 
     m.insert(std::pair<_pos,_val>(k2,v2)); 

     return 0; 
} 

El problema es que cuando intento compilar, consigo el error siguiente

$ g++ m2.cpp -o mtest 
In file included from /usr/include/c++/4.4/bits/stl_tree.h:64, 
       from /usr/include/c++/4.4/map:60, 
       from m2.cpp:1: 
/usr/include/c++/4.4/bits/stl_function.h: In member function ‘bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp = _pos]’: 
/usr/include/c++/4.4/bits/stl_tree.h:1170: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = _pos, _Val = std::pair<const _pos, _val>, _KeyOfValue = std::_Select1st<std::pair<const _pos, _val> >, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’ 
/usr/include/c++/4.4/bits/stl_map.h:500: instantiated from ‘std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = _pos, _Tp = _val, _Compare = std::less<_pos>, _Alloc = std::allocator<std::pair<const _pos, _val> >]’ 
m2.cpp:30: instantiated from here 
/usr/include/c++/4.4/bits/stl_function.h:230: error: no match for ‘operator<’ in ‘__x < __y’ 
m2.cpp:9: note: candidates are: bool _pos::operator<(_pos&) 
$ 

Pensé que declarar el operador < en la clave resolvería el problema, pero todavía está allí.

¿Qué podría estar mal?

Gracias de antemano.

+5

En C++ todos los identificadores que comienzan con un doble subrayado, un guión bajo seguido de una letra mayúscula o un solo subrayado seguido por una letra minúscula en el espacio de nombres global se reservan para la puesta en práctica. Los identificadores '_pos' y' _val' deben ser cambiados. –

+0

@David Rodríguez. Gracias, lo haré y lo tendré en cuenta. – Tom

Respuesta

25

El problema es el siguiente:

bool operator<(_pos& other) 

En caso de ser esto:

bool operator<(const _pos& other) const { 
//    ^^^^    ^^^^^ 

Sin la primera const, el lado derecho de la comparación (b en a < b) no puede ser const, ya sin const la función puede modificar su argumento.

Sin el segundo const, el lado izquierdo de la comparación (a en a < b) no puede ser const, ya que sin const la función puede modificar this.

Internamente, las claves de un mapa son siempre const.


Cabe señalar que debe preferir utilizar funciones que no sean miembros. Es decir, mejor es una función libre:

bool operator<(const _pos& lhs, const _pos& rhs) 
{ 
    return lhs.xi < rhs.xi; 
} 

En el mismo espacio de nombres que su clase. (Para nuestro ejemplo, justo debajo de ella.)


Por cierto, en C++ no es necesario para prefijar la declaración de una variable de tipo struct con struct. Esto es perfecto, y preferido:

_pos k1 = {0,10}; 
    _pos k2 = {10,15}; 

    _val v1 = {5.5}; 
    _val v2 = {12.3}; 

(Aunque sus nombres de tipos se denominan ciertamente de una manera poco ortodoxa:. P)


Por último, se debe preferir la función make_pair utilidad para la toma de pares:

m.insert(std::make_pair(k1,v1)); 
    m.insert(std::make_pair(k2,v2)); 

Le ahorra tener que escribir los tipos para el par, y es generalmente más fácil de leer. (Especialmente cuando aparecen nombres de tipos más largos.)

+0

Gracias por el consejo extra. – Tom

+0

@Tom: No hay problema, he agregado más. : P – GManNickG

+0

En este caso, la notación del subíndice es probablemente más clara que usar insertar directamente: 'm [k1] = v1; m [k2] = v2; '. –

4

La firma del operador menor que necesita ser bool operator<(const _pos& other) const, de lo contrario el mapa no puede usar este operador en las funciones const ya que esta función miembro se declara como no const.

4

Creo que su definición de operador < es incorrecta - el lado derecho (argumento en este caso) debe marcarse const y debe ser una función de miembro principal, p.

bool operator<(const _pos& other) const{ 

      return this->xi < other.xi; 
    } 
Cuestiones relacionadas