FerranMG
FerranMG

Reputation: 181

Why is map::find finding something it shouldn't be there?

I have defined these structs

typedef struct SApair
{
    SApair();
    SApair(State state, Action action);

    State state;
    Action action;

    bool operator<( const SApair& n) const
    { 
        return (this->state.m_avgDpsXHealthEnemyGroup < n.state.m_avgDpsXHealthEnemyGroup
                && this->state.m_avgDpsXHealthGroup < n.state.m_avgDpsXHealthGroup
                && this->state.m_distToClosestEnemyGroup < n.state.m_distToClosestEnemyGroup); //TODO - DEFINE A PROPER OPERATOR 
    }


} SApair;

struct State
{
    State();

    Group m_avgDpsXHealthGroup;
    Group m_avgHealthGroup; //LOW, MID, HIGH
    Group m_distToClosestEnemyGroup;
    Group m_avgDpsXHealthEnemyGroup; 
    Group m_avgEnemyHealthGroup;
}

and this enums

typedef enum x{ATTACK   = 0, 
               HOLD     = 1, 
               FLEE     = 2,
               COUNT    = 3} Action;


typedef enum y{NA       = -1, //Not Available
               LOW      = 0,
               MID      = 1,
               HIGH     = 2} Group;

I have a map

std::map<SApair, float>* q_map;

At one point, the map contains on single element (map size is 1):

sapair = {m_avgDpsXHealthGroup=-1 m_avgHealthGroup=-1_distToClosestEnemyGroup=-1 ...}
action = 0.0f

I create a new SApair element

SApair sapair = SApair(...);
sapair.state = {MID, LOW, HIGH, -1, -1} //This has been summed up by me for this stackoverflow post, but you get the idea
sapair.action = ATTACK;

So, clearly, sapair is different than what's in q_map[0].

However, the find method seems to be finding sapair in q_map

if(q_map->find(sapair) != q_map->end())
{
    //I don't understand why it enters here
}

What am I missing?

Could it be something with the < operator defined in SApair?

I certainly can't figure it out.

Any help will be appreciated.

Thanks.

Upvotes: 0

Views: 104

Answers (1)

sth
sth

Reputation: 229874

The operator< contains:

//TODO - DEFINE A PROPER OPERATOR

Which is appropriate and the source of the problem.

Currently the operator only return true if all three properties of the item's state are smaller than in the item it is compared to. If now for example two properties of an item a are smaller than for b and one is larger, then a < b returns false.

But b < a will also return false, since only property of b is smaller than the corresponding property of a.

Since neither a nor b are smaller than each other, they are considered to be equal.

Since unexpected items are considered to be equal this leads to unexpected results when searching for items with find().

A better operator<() would be:

bool operator<( const SApair& n) const
{ 
    if (this->state.m_avgDpsXHealthEnemyGroup < n.state.m_avgDpsXHealthEnemyGroup)
        return true;
    if (this->state.m_avgDpsXHealthGroup < n.state.m_avgDpsXHealthGroup)
        return true;
    if (this->state.m_distToClosestEnemyGroup < n.state.m_distToClosestEnemyGroup)
        return true;
    return false;
}

Upvotes: 4

Related Questions