BTreeSet 包含值(使用自定义 Ord 实现)并错误地为“contains”返回 true

Roy*_*son 2 traits rust

我有一个BTreeSet存储类型值的:

#[derive(Debug, Eq)]
pub struct Foo {
    pub a: usize,
    pub thing_to_compare: usize,
}

impl Ord for PriorityEntry {
    fn cmp(&self, other: &Self) -> Ordering {
        // Sort in reverse order
        other.thing_to_compare.cmp(&self.thing_to_compare)
    }
}

impl PartialOrd for PriorityEntry {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl PartialEq for PriorityEntry {
    fn eq(&self, other: &Self) -> bool {
        self.a == other.a && self.thing_to_compare == other.thing_to_compare
    }
}
Run Code Online (Sandbox Code Playgroud)

这个想法是,应该对 中的结构BTreeSet进行排序thing_to_compare,并且a字段只是附加信息。

我注意到如果我有BTreeSet一个

{ a: 0, thing_to_compare: 0 }
Run Code Online (Sandbox Code Playgroud)

然后containstrue返回

{ a: 1, thing_to_compare: 0 }
Run Code Online (Sandbox Code Playgroud)

我猜测它会返回true,因为cmp将返回Ordering::Equal两个值,因为它们具有相同的thing_to_compare. 我感到困惑的是为什么BTreeSet不使用自动生成的Eq特征或PartialEq特征来检查该值是否存在于其内部。

毕竟,我认为该Ord特征应该只与排序相关,而不与两个值是否相同相关。

Cod*_*256 6

文档Ord

PartialEqPartialOrd、 和的实现Ord 必须彼此一致。通过派生某些特征并手动实现其他特征,很容易意外地使他们产生不同意见。

换句话说,您需要确保(a == b) == (a.cmp(b) == Ordering::Equal)因为允许其他代码(例如BTreeSet)假设该属性成立;否则你可能会得到不正确(但并非不安全)的行为。