为什么 std::map 重载运算符<不使用比较

Why std::map overloaded operator < does not use the Compare

本文关键字:比较 std map 重载 运算符 为什么      更新时间:2023-10-16

从 http://www.cplusplus.com/reference/map/map/operators/我注意到:

"请注意,这些操作都没有考虑任一容器的内部比较对象,而是直接比较元素(类型为 value_type)。

这就是说重载运算符 "<" 在其声明中没有使用 Compare(参考 http://www.cplusplus.com/reference/map/map/)

std::map
template < class Key,                                     // map::key_type
           class T,                                       // map::mapped_type
           class Compare = less<Key>,                     // map::key_compare
           class Alloc = allocator<pair<const Key,T> >    // map::allocator_type
           > class map;

Compare在哪里

比较:将两个元素键作为参数的二进制谓词 并返回一个bool。表达式comp(a,b) ,其中 comp 是一个对象 此类型且ab是键值,如果 a 在严格的弱排序函数中被认为先于b 定义。map 对象使用此表达式来确定 元素在容器中的顺序以及是否两个元素 键是等效的(通过反射性比较它们:它们是 等效的如果!comp(a,b) && !comp(b,a)).地图中没有两个元素 容器可以具有等效的密钥。这可以是函数指针或 函数对象(有关示例,请参阅构造函数)。这默认为 less<T> ,返回与应用小于运算符相同的结果 (a<b) .别名为成员类型 map::key_compare

我不太明白,为什么不在"<"运算符中使用Compare

Compare用于比较key_type。 地图的<运算符实际上是比较mapped_type value_type,而不是key_type,所以Compare不适用。 value_typekey_typemapped_type的一对。

不过,老实说,我认为首先给地图一个operator<是运算符重载过分的情况。 说一张地图"小于"另一张地图是什么意思并不明显。 如果你想要lexigraphical_compare,我建议直接调用它,或者至少在你的代码中记录你的地图比较意味着什么。

为什么std::map过载operator <不使用Compare

一个很好的理由是,确保行为有意义并不容易。假设Compare函子可以是有状态的,则两个相同类型的映射可能具有完全不同的排序条件。例如

struct Cmp
{
  Comp(bool flip) : flip(flip) {}
  bool operator()(int lhs, int rhs) const
  {
    return flip ? lhs < rhs : rhs < lhs;
  }
  bool flip;
};

这两个映射具有相同的类型,但顺序不同:

std::map<int, std::string, Cmp> m0(Cmp(false));
std::map<int, std::string, Cmp> m1(Cmp(true));
bool b = m0 < m1; // which Cmp should this use?

这不一定是使用<等的理由,而是不使用Compare的好理由。