Rust 抱怨在执行联合时 BitOr 没有为 HashSet 实现,文档指出它应该是

nai*_*eai 3 hashset rust

最小示例:

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
}
Run Code Online (Sandbox Code Playgroud)

在 Rust Playground 上检查一下。如果您尝试编译此代码,Rust 会抱怨error[E0369]: no implementation for std::collections::HashSet<Point> | std::collections::HashSet<Point>.

但根据HashSet 的文档,至少根据我的理解,BitOr应该为 HashSet 实现该特征,其中T: Eq + Hash + Clone,Point显然在这里。那么到底发生了什么,我该如何解决呢?

Bri*_*ian 5

仔细看看for的实现BitOrHashSet:

impl<T, S> BitOr<&HashSet<T, S>> for &HashSet<T, S>
where
   ...
Run Code Online (Sandbox Code Playgroud)

BitOr仅针对对HashSets 的引用实现,而不针对拥有的值实现。

按如下方式重写您的实现Something::TEST将按预期进行编译。

impl Something {
    fn TEST(&self) {
        let new = &self.a | &self.b;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,这使用了对self.a和 的引用self.b。


事实上,像按位或这样的操作仅针对对容器的引用而不是针对容器类型本身来实现,这一事实乍一看似乎是出乎意料的,但当您考虑它们预期的所有权语义时,它就完全有意义了。的签名bitor是fn bitor(self, rhs: T),它拥有 和 的self所有权rhs。如果BitOr(或任何其他二元运算符特征)被实现为不是 的类型的目录Copy,那么它将获得 的参数的所有权|。导致a | ba 或 b 被移动将是相当意外的。因此,标准库仅实现二元运算符来引用集合(可以Copy),而不是集合值本身。