C++:为什么返回false的集合顺序的函子只允许向集合中添加一个元素



我编写了以下函子,期望集合中的所有元素都将按插入的相反顺序添加:

struct cmp {
  bool operator () (int a, int b) {
    return false;
  }
};  

当我按照下面的方式测试它时,添加到集合中的唯一值是1。

int main() {
  set<int, cmp > combos;
  combos.insert(1);
  combos.insert(4);
  combos.insert(7);
  combos.insert(5);
  combos.insert(9);
  combos.insert(1);
  for (int a : combos) {
    cout << a << endl;
  }
  return 0;
}

然而,当我每次将函子更改为返回true时,所有值都会按照插入[1, 4, 7, 5, 9, 1]的顺序添加到集合中。我想,当函子比较器返回true时,它被视为第一个元素小于第二个元素,而false意味着第一个元素被视为比第二个更大?这似乎是我在运算符函数中执行return (a < b);return (a > b);时的情况。

比较函数需要在元素上定义一个严格的弱序。也就是说,这三个条件需要适用于所有元素,abc:

  1. a < afalse(不可伸缩性)
  2. a < btrue意味着b < afalse(不对称性)
  3. a < bb < c都是true暗示a < c也是true(传递性)

当使用比较器对象cmp时,需要应用上述条件,其中x < ycmp(x, y)代替。

然而,第一个比较函数(总是返回false)实际上是一个严格的弱序,它意味着所有元素都是等价的。没有办法区分这两个要素。特别地,a < bb < a都不产生true。如果这两个条件都是false,那么这两个对象显然是等价的。因此,集合中只有一个元素。

第二个比较函数(总是返回true)不是严格的弱阶,因为它违反了第一个条件(不可伸缩性)。集合中发生的任何事情都是未定义的行为。

在这种情况下,std::set使用!(a < b) && !(b < a)来确定两个元素的相等性:ab

当检查重复项时,!(false) && !(false)每次都将产生true,因此不允许std::set包含多个元素。这是对CCD_ 35的滥用。

最新更新