Reputation: 316
I am using Qt 4.7.4 with MS Visual C++ 2010.
I am using the following QMap:
QMap<T_FileMapKey, HANDLE> m_oMapHistHandle;
where T_FileMapKey is defined as:
typedef struct tagT_FileMapKey
{
int iSubscriptIdx;
int iFilterIdx_1;
int iFilterIdx_2;
} T_FileMapKey;
In order to get the whole thing going, I have overloaded the < operator:
bool operator< (const T_FileMapKey& tVal1, const T_FileMapKey& tVal2)
{
if(tVal1.iSubscriptIdx < tVal2.iSubscriptIdx)
{
return true;
}
else
{
if(tVal1.iFilterIdx_1 < tVal2.iFilterIdx_1)
{
return true;
}
else
{
if (tVal1.iFilterIdx_2 < tVal2.iFilterIdx_2)
{
return true;
}
else
{
return false;
}
}
}
};
As you may predicted this entire operation is to store file handles in a 3 dimensional array like order. I am using a QMap since only a few combinations of the indexes is used and they may be large numbers.
My problem is:
if (INVALID_HANDLE_VALUE == m_oMapCurrHandle.value(tFileKey, fdInvalidHandle))
....
and
if (false == m_oMapHistHandle.contains(tFileKey))
....
(where tFileKey is a T_FileMapKey variable) does not always return the correct value.
Under normal circumstances the QMap is growing over the time, meaning that if a new index combination is encountered a file is opened and the entry is added to the QMap. If I launch the application in debug mode the Qt Visual Studio Add-in allows me to peek into the stored key-value pairings. I can see that the entry in the debug Watch is present (e.g. {0, 32767, 0}) but the two function calls (contains and value) tell me that the QMap does not have such key stored. Usually this behavior is encountered after the QMap has at least 15 key-value pairs.
May this be a bug in Qt 4.7.4? What am doing wrong?
Upvotes: 1
Views: 1827
Reputation: 66
I think your problem is in your less operator because you never compare with greater sign. You should have something like that :
bool operator< (const T_FileMapKey& tVal1, const T_FileMapKey& tVal2)
{
if(tVal1.iSubscriptIdx < tVal2.iSubscriptIdx)
{
return true;
}
else if (tVal2.iSubscriptIdx < tVal1.iSubscriptIdx)
{
return false ;
}
else
{
if(tVal1.iFilterIdx_1 < tVal2.iFilterIdx_1)
{
return true;
}
else if (tVal2.iFilterIdx_1 < tVal1.iFilterIdx_1 )
{
return false ;
}
else
{
if (tVal1.iFilterIdx_2 < tVal2.iFilterIdx_2)
{
return true;
}
else
{
return false;
}
}
}
};
I used only less operator because you may not have other defined
Upvotes: 0
Reputation: 302738
Your operator<
is wrong. To explain, Let's consider a simpler cause for writing operator<
for just pair<int, int>
. Your version is implemented thusly:
bool operator<(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
if (lhs.first < rhs.first) {
return true; // (1)
}
else if (lhs.second < rhs.second) {
return true; // (2)
}
else {
return false; // (3)
}
}
So {1,4}
< {2,3}
because of (1). But {2,3}
< {1,4}
because of (2)! So we end up with an operator<
that doesn't establish an ordering.
The simplest way to establish a lexicographical comparison would be to completely deal with each term in turn:
bool operator<(const pair<int, int>& lhs, const pair<int, int>& rhs)
{
if (lhs.first != rhs.first) {
return lhs.first < rhs.first;
}
else {
return lhs.second < rhs.second;
}
}
The same idea can be easily extended to your triple.
Upvotes: 4