Milow Milow - 3 months ago 23
C++ Question

std::map erase wrong element

When I try to erase elements of my map, it seems to be an another element who is erased instead.
I thought it was a bad override of operator< but I don't see the problem.

inline bool operator<(const Etat &et){
if (et.x < this->x){
return false;
}
else if (et.x > this->x){
return true;
}
if (et.y < this->y){
return false;
}
else if (et.y > this->y){
return true;
}
if (et.ry < this->ry){
return false;
}
else if (et.ry > this->ry){
return true;
}
};


Etat constructor :

Etat(x, y, ry, useless, useless);


and the map :

std::map< Etat, double > map;
//The 2 last parameters of Etat are useless
map.insert(std::pair< Etat, double >(Etat(2, 2, 2, 0, 0), 0.0));
//map.size() = 1
Etat e (0, 5 ,3, 0, 0);
map.erase(e);
//map.size() = 0
//Etat(2, 2, 2) is gone


I don't have the problem for all instance of Etat in the map, just this case on and some others.

Test it at home :

#ifndef Etat_H
#define Etat_H

#include<iostream>

class Etat
{
public:
Etat(const int x, const int y, const int ry, const double vx, const double vy)
{
this->x = x;
this->y = y;
this->ry = ry;
this->vx = vx;
this->vy = vy;
};

Etat(){};
inline bool operator==(const Etat& et){
if (et.x == this->x && et.y == this->y && et.ry == this->ry && et.vx == this->vx && et.vy == this->vy){
return true;
}
return false;
};
inline bool operator!=(const Etat& et){
if (*this == et){
return false;
}
return true;
};
inline bool operator<(const Etat &et){
if (et.x < this->x){
return false;
}
else if (et.x > this->x){
return true;
}
if (et.y < this->y){
return false;
}
else if (et.y > this->y){
return true;
}
if (et.ry < this->ry){
return false;
}
else if (et.ry > this->ry){
return true;
}
};

inline bool operator>(const Etat& et){
if (*this < et){
return false;
}
return true;
};

inline const int getX() const {
return this->x;
};

inline const int getY() const {
return this->y;
};

inline const int getRY() const {
return this->ry;
};

private:
int x, y;
int ry;
double vx, vy;
};

#endif // !Etat_H


The little piece of code can reproduce the problem :

std::map< Etat, double > map;
map.insert(std::pair< Etat, double >(Etat(2, 2, 2, 0, 0), 0.0));
Etat e (0, 5 ,3, 0, 0);
map.erase(e);

Answer

To use your class as a key in map, you must define when your elements are equal. So define comparator class:

struct EtatCompare {
   bool operator() (const Etat& e1, const Etat& e2) const {
       return e1.x != e2.x || e1.y != e2.y || e1.ry != e2.ry || e1.vx != e2.vx || e1.vy != e2.vy; //TODO: fill all the needed conditions here
   }
};

And use it creating map:

std::map< Etat, double, EtatCompare > map;
Comments