Rust抱怨在执行联合时没有为HashSet实现BitOr,而文档中却规定应该实现

vojdkbi0  于 2022-12-23  发布在  其他
关注(0)|答案(1)|浏览(106)

最小示例:

use std::collections::HashSet;

struct Something {
    a: HashSet<Point>,
    b: HashSet<Point>
}

impl Something {
    fn TEST(&self) {
        let new = self.a | self.b;
    }
}

#[derive(Eq, PartialEq, Hash, Copy, Clone)]
struct Point {
    x: usize,
    y: usize
}

检查它on the Rust Playground。如果你试图编译这段代码,Rust会用error[E0369]: no implementation for std::collections::HashSet<Point> | std::collections::HashSet<Point>抱怨。
但是根据HashSet的文档,至少根据我的理解,应该为HashSet实现BitOr特性,其中T: Eq + Hash + ClonePoint显然在这里,那么实际上发生了什么,我如何修复它?

c0vxltue

c0vxltue1#

进一步了解HashSetBitOr实现:

impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where
   ...

BitOr仅针对对HashSet的引用而实现,不针对拥有的值而实现。
按如下所示重新编写Something::TEST的实现将按预期进行编译。

impl Something {
    fn TEST(&self) {
        let new = &self.a | &self.b;
    }
}

请注意,这里使用了对self.aself.b的引用。
像按位或这样的操作只对容器的引用而不是容器类型本身实现,这一事实一开始可能看起来出乎意料,但是当你考虑到它们预期的所有权语义时,它就完全有意义了。它同时拥有selfrhs。如果BitOr(或任何其它二元运算符特征)在不是Copy的类型的目录中实现,那么它将取得|的自变量的所有权。使a | b导致a或b被移动将是相当出乎意料的。因此,标准库仅实现用于引用集合(其是Copy能力的)的二元运算符,而不是用于引用集合值本身的二元运算符。

相关问题