How to use struct as a key of std::map in C++, and its pitfall

We can use a structure and a class, which are defined by myself, as key of std::map.

If we want to do so, we need define comparison operator < for defined structure or class, because std::map stores data  as binary tree. If we don’t define <, computer can not decide which one is bigger or smaller.

I show the sample code below. In this sample, a structure, which has an int and char[100] as its member, works a key of std::map.

/**
* @struct intStringKey_t
* @brief This struct is int-string key for map
*/
struct intStringKey_t{
int intKey;
char stringKey[100];
bool operator < (const intStringKey_t& rhs ) const {
  if (intKey_t < rhs.intKey_t) { 
    return true; 
  } 
  if (intKey_t > rhs.intKey_t) {
    return false;
  }
  if ((strcmp(stringKey, rhs.stringKey)) < 0) { 
    return true; 
  } 
  if ((strcmp(stringKey, rhs.stringKey)) > 0) {
    return false;
  }
  return false;
  }
};// intStringKey_t;

If you define a structure like this, you can use this structure as a key of std::map.

Of course, you can select another implementation of comparison operator < .

 

Well, when I use a structure as a key of std::map, I encounter a pitfall. Corresponding code is like this:

/**
 * @struct intStrKey_t
 * @brief This struct can NOT be used as int-string key for map
 */
struct intStrKey_t{
  int intKey;
  char strKey[100];
  bool operator < (const intStrKey_t&rhs ) const {
    if (intKey < rhs.intKey) {
      return true;
    } else if (intKey == rhs.intKey) {
      if (strcmp(strKey, rhs.strKey)) {
        return true;
      } else {
        return false;
      }
    } else {
      return false;
    }
  }
};// intStrKey_t;

Do you find a bug soon?

In this definition, when two ints are equal, < returns false if two chars equal. If two chars are not equal, < returns true.
Therefore, this < returns true even if result of strcmp is 1 or -1.

This is an obstacle for search of binary tree.

I think this is a careless mistake, however,  I spent time to fix this bug. Because when the map includes only one data, there is no problem!
After the map stores second data, I could not retrieve that data from the map, even if retrieve it immediately. Additionally, I could retrieve third data…

At first, I guess I wrote a code which destroys the memory around std::map code, because it seems to behave in an erratic way. However, I could not find such code even if I read and reread the code.

Finally, I could find the definition of structure(implementation of comparison operator <) is incorrect, however, I spent time to find it.

If this article helps someone who meets similar problem, I feel happy! 😀


Leave a Reply

Your email address will not be published. Required fields are marked *