Search code examples
c++comparator

C++ map with custom comparator is not inserting all elements


I have the following code:

enum Type {
  OUTPUT = 1,
  INPUT = 2,
  INOUT = 3
};

std::vector<int> data = {INPUT, INOUT, OUTPUT, INPUT, OUTPUT, INPUT}

My goal is to store information into a std::map<int, char> where the key is index in data and value is some character. I want it to be ordered in such a way that those indexes for which in data they have value INPUT would be in the beginning.

I tried to write a custom comparator:

struct Comparator {
  bool operator()(int lhs, int rhs) {
    if (data[lhs] == INPUT && data[rhs] != INPUT) {
      return true;
    } else if (data[lhs] != INPUT && data[rhs] == INPUT) {
      return false;
    }

    return data[lhs] < data[rhs]
  }
};

But for the following code

int main()
{
  std::map<int, char, Comparator> m;

  for (unsigned i = 0; i < data.size(); ++i) {
    m.insert( {i, 'a' + i} );
  }
}

my map's values are

0 -> 'a'
2 -> 'c'
1 -> 'b'

I expected to have 6 elements in it, first three being 0 -> 'a', 3 -> 'd', 5 -> 'f'


Solution

  • You order based on values stored in data and you only have 3 values stored in there, so you can only get 3 values in the map at most.

    Your ordering should be based on lhs and rhs rather than data[lhs]/data[rhs]:

    struct Comparator {
      bool operator()(int lhs, int rhs) const /* note the const here */ {
        if (data[lhs] == INPUT && data[rhs] != INPUT) {
          return true;
        } else if (data[lhs] != INPUT && data[rhs] == INPUT) {
          return false;
        }
    
        // either both are INPUT or both are not,
        // so compare lhs and rhs, not the values in data
        return lhs < rhs; 
      }
    };
    

    See it online