3

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!

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
user2347261
  • 43
  • 1
  • 5
  • 3
    You may find this helpful http://stackoverflow.com/questions/16340680/creating-a-composite-type-from-two-enum-classes-ready-for-stl-map/16341009#16341009 which uses `std::tie`. If you do not have c++11 then `boost::tie` is available. – hmjd May 03 '13 at 15:17

2 Answers2

8

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.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • I don't have tuple available to me in this project. I appreciate the info though and will look into ties in the future. Thanks! – user2347261 May 03 '13 at 18:15
  • If the keyA, keyB, etc were floats, how does this effect the stability of using such a structure as a key in a map? While using a single float as a map key is prone to error, is this combination of floats using `std::tie` any better? – johnbakers Jan 04 '17 at 10:08
6

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.

john
  • 7,897
  • 29
  • 27