I have been trying defining a custom comparator for std::map container.
The question is : can I relay on == and != operators or would that break strict weak order ? Am I forced to use operator < ?
(One and Two classes do have operator!= and operator== defined correctly)
typedef std::pair<One, Two> MapKey_t;
class cmp
{
bool operator()(const MapKey_t& left, const MapKey_t& right) const
{ return left.first != right.first && right.first == right.second; }
}
typedef std::map<MapKey_t, Three*, cmp> MyMap_t;
Since switching left with right would not change the comparator return value, will this be working?
I don’t really care about how the items are sorted into the container, but I do not want duplicates to be part of it.
Update :
can I use the memory address to obtain strict weak ordering ?
class cmp
{
bool operator()(const MapKey_t& left, const MapKey_t& right) const
{
if(left.first == right.first)
if(left.second != right.second)
return false; // This represents for me, functionally, a duplicate
else
// Can't use operator < there since left.second equals right.second but
// functionally for me, this is not a duplicate and should be stored
// what about memory address strict weak ordering ?
return &left < &right;
else
return left.first < right.first; // There I can use operator <
}
You cannot rely on self consistent equals or not equals because these do not establish a strict weak ordering. The comparator return value should change if you switch the left and right arguments. It is essential for the map to be able to establish an ordering of elements, not just be able to distinguish whether two elements are equal.
It is very important that, is
A < Bis true, thenB < Ais false. Furthermore, ifA < BandB < Care both true, thenA < Cis also true.If you do not want to or cannot establish a strict weak ordering for your types, then, then you could use a map that doesn’t require it:
std::unordered_map1, which is a hash map. However, this will require that you provide a hashing function and an equality comparison. It also requires that your compiler have C++11 support.1 As @JohnDibling points out in comments,
std::unordered_mapis unfortunately named. It should have beenstd::hash_mapbut apparently that name could have clashed withhash_mapsfrom other libraries. In any case, the intent is not to have a map that is not ordered, but to have one with constant time look-up.