特征实现调用相似名称的函数
Trait implementation calling a function of similar name
尝试抽象一些我只需要 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)
}
}
我在编译时收到关于递归的警告,而我“显然”不想递归而是在实现者上使用底层实现。
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)
我原以为只有在指定的情况下才会发生递归(self as Set<T>).insert
解决这个问题的惯用方法是什么?
您可以构建一个包装器类型来解决这个问题:
use std::collections::HashSet;
trait Set<T> {
fn insert(self: &mut Self, item: T);
fn contains(self: &Self, item: T) -> bool;
}
struct HashSetWrapper<T> {
hash_set: HashSet<T>
}
impl<T> Set<T> for HashSetWrapper<T>
where T: Eq + std::hash::Hash
{
fn insert(&mut self, item: T) {
self.hash_set.insert(item);
}
fn contains(&self, item: T) -> bool {
self.hash_set.contains(&item)
}
}
注意 T 必须实现 Eq +
哈希
你是对的 HashSet::insert
应该优先于你的特征函数。
但问题是 HashSet::insert
实际上需要 T
来实现 Eq + Hash
。由于您的 T
不受限制,因此不考虑 HashSet::insert
,唯一可用的 insert
是 Set
特征,您会得到意外的递归。
要发现这一点,您可以尝试编译:
fn insert(&mut self, item: T) {
HashSet::insert(self, item);
}
并得到错误:
error[E0277]: the trait bound `T: std::cmp::Eq` is not satisfied
幸运的是,Rustc 的人已经考虑到这种错误的可能性(我也发生过)并添加了一个非常有用的警告。
如果将其更改为:
impl<T: std::cmp::Eq + std::hash::Hash> Set<T> for HashSet<T> {
fn insert(&mut self, item: T) {
self.insert(item);
}
}
然后就可以了。 (不过,还有其他不相关的错误。)
使用专门调用:
impl<T> Set<T> for HashSet<T> where T: std::cmp::Eq + std::hash::Hash {
fn insert(&mut self, item: T) {
HashSet::insert(self, item);
}
fn contains(&self, item: T) -> bool {
HashSet::contains(self, &item)
}
}
尝试抽象一些我只需要 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)
}
}
我在编译时收到关于递归的警告,而我“显然”不想递归而是在实现者上使用底层实现。
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)
我原以为只有在指定的情况下才会发生递归(self as Set<T>).insert
解决这个问题的惯用方法是什么?
您可以构建一个包装器类型来解决这个问题:
use std::collections::HashSet;
trait Set<T> {
fn insert(self: &mut Self, item: T);
fn contains(self: &Self, item: T) -> bool;
}
struct HashSetWrapper<T> {
hash_set: HashSet<T>
}
impl<T> Set<T> for HashSetWrapper<T>
where T: Eq + std::hash::Hash
{
fn insert(&mut self, item: T) {
self.hash_set.insert(item);
}
fn contains(&self, item: T) -> bool {
self.hash_set.contains(&item)
}
}
注意 T 必须实现 Eq + 哈希
你是对的 HashSet::insert
应该优先于你的特征函数。
但问题是 HashSet::insert
实际上需要 T
来实现 Eq + Hash
。由于您的 T
不受限制,因此不考虑 HashSet::insert
,唯一可用的 insert
是 Set
特征,您会得到意外的递归。
要发现这一点,您可以尝试编译:
fn insert(&mut self, item: T) {
HashSet::insert(self, item);
}
并得到错误:
error[E0277]: the trait bound `T: std::cmp::Eq` is not satisfied
幸运的是,Rustc 的人已经考虑到这种错误的可能性(我也发生过)并添加了一个非常有用的警告。
如果将其更改为:
impl<T: std::cmp::Eq + std::hash::Hash> Set<T> for HashSet<T> {
fn insert(&mut self, item: T) {
self.insert(item);
}
}
然后就可以了。 (不过,还有其他不相关的错误。)
使用专门调用:
impl<T> Set<T> for HashSet<T> where T: std::cmp::Eq + std::hash::Hash {
fn insert(&mut self, item: T) {
HashSet::insert(self, item);
}
fn contains(&self, item: T) -> bool {
HashSet::contains(self, &item)
}
}