std::map,自定义比较器的设计约束

std::map, custom comparator's design constraints

本文关键字:设计约束 比较器 map std 自定义      更新时间:2023-10-16

我一直在尝试为std::map容器定义一个自定义比较器。

问题是:我能在==和!=上中继吗运算符还是会打破严格的弱秩序?我是否被迫使用运算符<

(一个和两个类确实有运算符!=和运算符==定义正确)

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;

由于左右切换不会改变比较器的返回值,这会起作用吗?

我真的不在乎如何将项目排序到容器中,但我不希望重复成为其中的一部分。

更新

我可以使用内存地址来获得严格的弱排序吗?

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 <
}

不能依赖自洽的等于或不等于,因为它们不能建立严格的弱排序。如果切换左右参数,则比较器返回值发生更改。地图必须能够建立元素的顺序,而不仅仅是能够区分两个元素是否相等。

非常重要的是,如果A < B为真,那么B < A为假。此外,如果A < BB < C都为真,则A < C也为真。

如果你不想或不能为你的类型建立严格的弱排序,那么,你可以使用一个不需要的映射:std::unordered_map1,这是一个哈希映射。但是,这需要您提供一个散列函数和一个相等性比较。它还要求编译器支持C++11。

1 正如@JohnDining在评论中指出的,std::unordered_map不幸被命名。它应该是std::hash_map,但显然这个名称可能与其他库中的hash_maps冲突。在任何情况下,目的都不是要有一个没有顺序的映射,而是要有一张具有恒定时间查找的映射

您可能不关心事物在映射中的顺序,但映射确实关心。上面提供的代码似乎没有正确实现严格的弱排序。正如您已经注意到的,在所有情况下,以左换右不会改变operator()的结果,您的函数并没有实现严格的弱排序。

您不必直接根据operator<来实现比较器,但必须确保如果operator()(A,B)返回true,那么operator()(B,A)也不会返回true

这是不可接受的,字符串弱排序意味着A < BB < A不应同时为真。std::map依赖于此来建立密钥的排序和相等性