试图抽象一些我只需要Set我编写的操作的算法
use std::collections::HashSet;
trait Set<T> {
fn insert(self: &mut Self, item: T);
fn contains(self: &Self, item: T) -> bool;
}
impl<T> Set<T> for HashSet<T> {
fn insert(&mut self, item: T) {
self.insert(item);
}
fn contains(&self, item: T) -> bool {
self.contains(item)
}
}
impl<T> Set<T> for Vec<T> {
fn insert(&mut self, item: T) {
self.push(item);
}
fn contains(&self, item: T) -> bool {
self.contains(item)
}
}
Run Code Online (Sandbox Code Playgroud)
我在编译时收到有关递归的警告,而我“显然”不想递归,而是在实现者上使用底层实现。
function cannot return without recursing
cannot return without recursing
note: `#[warn(unconditional_recursion)]` on by default
help: a `loop` may express intention better if this is on purposerustc(unconditional_recursion)
Run Code Online (Sandbox Code Playgroud)
我希望只有在指定的情况下才会发生递归 (self as Set<T>).insert
解决这个问题的惯用方法是什么?
你是对的,HashSet::insert应该优先于你的特征函数。
但问题是HashSet::insert实际上需要T实现Eq + Hash. 由于您T不受限制,HashSet::insert因此不考虑,唯一insert可用的是Set特征,并且您会得到意外的递归。
要发现这一点,您可以尝试编译:
fn insert(&mut self, item: T) {
HashSet::insert(self, item);
}
Run Code Online (Sandbox Code Playgroud)
并得到错误:
error[E0277]: the trait bound `T: std::cmp::Eq` is not satisfied
Run Code Online (Sandbox Code Playgroud)
幸运的是,Rustc 的人已经考虑到了这种错误的可能性(我也遇到过),并添加了一个非常有用的警告。
如果您将其更改为:
impl<T: std::cmp::Eq + std::hash::Hash> Set<T> for HashSet<T> {
fn insert(&mut self, item: T) {
self.insert(item);
}
}
Run Code Online (Sandbox Code Playgroud)
那么它的工作原理。(不过,还有其他不相关的错误。)