user2347261
user2347261

Reputation: 43

Comparison Operator for Structure key in C++ Map Table

I have data that is uniquely identified by a combination of 3 integers.

For example:
Item #1: 10,20,1
Item #2: 10,21,0
Item #3: 0,14,13
Item #4: 103,324,78

My structure:

struct structureKeyID
{
    int keyA;
    int keyB;
    int keyC;

    // Comparison operator for table sorting.
    bool operator<(const structureKeyID& param) const
    {
        if (keyA < param.keyA) return true;
        if (keyB < param.keyB) return true;
        if (keyC < param.keyC) return true;
        return false;
    }
};

map <structureKeyID, classDataRecord> tableRecords;

I've found if I add a key (0,0,1):

structureKeyID keyID1;
keyID1.keyA = 0;
keyID1.keyB = 0;
keyID1.keyC = 1;
tableRecords[keyID1] = <data>;

I then check if key (0,1,0) exists:

structureKeyID keyID2;
keyID1.keyA = 0;
keyID1.keyB = 1;
keyID1.keyC = 0;
if (tableRecords.find(keyID2) != tableRecords.end())

Then I will get an error:

Debug Assertion Failed!
\include\xtree Line: 1268
Expression: invalid operator

Whereas, if I check if key (0,0,2) or if key (10,0,2) exists it works fine.

What is the proper way to build the comparison operator for this situation?

Thank you very much!

Upvotes: 3

Views: 4091

Answers (2)

juanchopanza
juanchopanza

Reputation: 227608

The easiest implementation of a less-than comparison satisfying strict weak ordering is with std::tie, available in the <tuple> header:

bool operator<(const structureKeyID& param) const
{
  return std::tie(keyA, keyB, keyC) < std::tie(param.keyA, param.keyB, param.keyC);
}

This performs a lexicographical comparison. If you don't have C++11 support, you can find equivalents in TR1 and Boost.

Upvotes: 8

john
john

Reputation: 8027

Try this

// Comparison operator for table sorting.
bool operator<(const structureKeyID& param) const
{
    if (keyA < param.keyA) return true;
    if (keyA > param.keyA) return false;
    if (keyB < param.keyB) return true;
    if (keyB > param.keyB) return false;
    if (keyC < param.keyC) return true;
    if (keyC > param.keyC) return false;
    return false;
}

Your version doesn't define a consistent ordering (the technical term is a strict weak ordering) because with your comparison function it would be possible to have A < B < C < A, so std::map gets confused.

Upvotes: 6

Related Questions