NewToCPP wrote:
I am having problem with key compare in stl map. Below is part of my
code .. could anyone tell me what might be wrong here...
I am using VC++ 6.0
code:
=====
class MyKey
{
public:
unsigned long value;
unsigned long type
bool operator<(const MyKey& right)
{
return ( type< right.type) &&
( value < right.value );
}
};
class MapTest
{
public:
std::map<MyKey, MyClass* myMap;
MapTest();
~MapTest();
void addElement(MyClass* pClass);
OmciCommonMe* findElement(MyKey key);
};
Error:
-------
c:\program files\microsoft visual studio\vc98\include\functional(86) :
error C2678: binary '<' : no operator defined which takes a left-hand
operand of type 'const class MyKey' (or there is no acceptable
conversion)
The solution is to provide either a const member op< or a global friend
op< as already mentioned
Since presumeably you'll want private data in a critical Key:
class MyKey
{
unsigned long type;
unsigned long value;
public:
MyKey(long t, long v) : type(t), value(v) { }
unsigned long getType() const { return type; }
unsigned long getValue() const { return value; }
friend bool operator<(const MyKey&, const MyKey&);
};
bool operator<(const MyKey& lhv, const MyKey& rhv)
{
// the following comparison will FAIL
eturn (lhv.type < rhv.type) && (lhv.value < rhv.value );
}
The above return says that left is less than right only if *both*
members are less. Not good.
Don't forget that you are using a map. If the op< fails to process the
key order, inserts will be dropped silently on duplicates. Which is
what would happen here.
The operator needs to
a) check whether the left type is less than the right type, if not...
OR
b) are they equal? if so... AND
c) then return whether the left value is less than the right value
translation:
bool operator<(const MyKey& lhv, const MyKey& rhv)
{
return ((lhv.type < rhv.type) || ((lhv.type == rhv.type) &&
(lhv.value < rhv.value )) );
}
and just for the hell of it, here is a test:
int main()
{
std::map<MyKey, std::string m;
m.insert( std::make_pair(MyKey(0,0), "string_00") );
m.insert( std::make_pair(MyKey(1,2), "string_12") );
m.insert( std::make_pair(MyKey(2,2), "string_22") );
m.insert( std::make_pair(MyKey(1,1), "string_11") );
m.insert( std::make_pair(MyKey(2,1), "string_21") );
m.insert( std::make_pair(MyKey(3,3), "string_33") );
typedef std::map<MyKey, std::string >::iterator MIter;
for(MIter miter = m.begin(); miter != m.end(); ++miter)
{
std::cout << (*miter).first.getType() << "\t";
std::cout << (*miter).first.getValue() << "\t";
std::cout << (*miter).second << std::endl;
}
}
/*
0 0 string_00
1 1 string_11
1 2 string_12
2 1 string_21
2 2 string_22
3 3 string_33
*/