我编写了以下函子,期望集合中的所有元素都将按插入的相反顺序添加:
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);
时的情况。
比较函数需要在元素上定义一个严格的弱序。也就是说,这三个条件需要适用于所有元素,a
、b
、c
:
a < a
是false
(不可伸缩性)a < b
是true
意味着b < a
是false
(不对称性)a < b
和b < c
都是true
暗示a < c
也是true
(传递性)
当使用比较器对象cmp
时,需要应用上述条件,其中x < y
被cmp(x, y)
代替。
然而,第一个比较函数(总是返回false
)实际上是一个严格的弱序,它意味着所有元素都是等价的。没有办法区分这两个要素。特别地,a < b
和b < a
都不产生true
。如果这两个条件都是false
,那么这两个对象显然是等价的。因此,集合中只有一个元素。
第二个比较函数(总是返回true
)不是严格的弱阶,因为它违反了第一个条件(不可伸缩性)。集合中发生的任何事情都是未定义的行为。
在这种情况下,std::set
使用!(a < b) && !(b < a)
来确定两个元素的相等性:a
和b
。
当检查重复项时,!(false) && !(false)
每次都将产生true
,因此不允许std::set
包含多个元素。这是对CCD_ 35的滥用。