dragan.stepanovic
dragan.stepanovic

Reputation: 3005

Problem with count() and find() in std::multimap

I want to use std::multimap whose Keys and Values are of type GUID. For that, I needed to define comparison operator. Here is the related question.

struct GUIDPairsComparer
{
    bool operator()(const GUID &left, const GUID &right) const
    {

      if (left.Data1 < right.Data1)
        return true;     
      if (left.Data2 < right.Data2)
        return true;
      if (left.Data3 < right.Data3)
        return true;

      return false;

    }
};

Class A{

  private:
      multimap<GUID, GUID, GUIDPairsComparer> myMap;
      multimap<GUID, GUID, GUIDPairsComparer>::iterator it_myMap;

  public:
      FunctionUsingMultiMap(){...}

};

But, I have difficulties when using myMap.count(GUID x) and myMap.find(GUID x). Using myMap.count(GUID x) produces exception, while when I use myMap.find(GUID x) with the GUID element that I know for sure is in the multimap, I get the iterator to the last element in multimap, which means that the given element is not found in multimap.

Do you, by any means, have a clue why is this happening?
Somehow I think it's related to comparison operator I've defined in the structure which afterwards I use for multimap construction, but I don't know exactly why. Also here is a definition of GUID type:

typedef struct _GUID {
    unsigned long  Data1;
    unsigned short Data2;
    unsigned short Data3;
    unsigned char  Data4[ 8 ];
} GUID;

As you can see, I've used Data1, Data2 and Data3 in comparison function, but didn't use Data4 char array since I don't see any logical way to compare that part of GUID.

Upvotes: 1

Views: 657

Answers (2)

Jo&#227;o Augusto
Jo&#227;o Augusto

Reputation: 2305

bool operator<(const GUID & Left, const GUID & Right)
    {
        if(Left.Data1 == Right.Data1)
        {
            if(Left.Data2 == Right.Data2)
            {
                if(Left.Data3 == Right.Data3)               
                    return (memcmp(left.Data4, right.Data4, 8) < 0);                                
                else
                    return Left.Data3 < Right.Data3;
            }
            else
                return Left.Data2 < Right.Data2;
        }
        else
            return Left.Data1 < Right.Data1;
    }

Upvotes: 2

Erik
Erik

Reputation: 91260

Your comparison operator is wrong - it doesn't satisfy strict weak ordering.

if (left.Data1 < right.Data1)
    return true; 
else if (left.Data1 > right.Data1)
    return false;
if (left.Data2 < right.Data2)
    return true; 
else if (left.Data2 > right.Data2)
    return false;    
if (left.Data3 < right.Data3)
    return true; 
else if (left.Data3 > right.Data3)
    return false;
return memcmp(left.Data4, right.Data4, 8) < 0;

Upvotes: 5

Related Questions