如何在Rust中的外部数据类型上实现std::hash::hash特性?

如何在Rust中的外部数据类型上实现std::hash::hash特性?,rust,hashset,refcell,Rust,Hashset,Refcell,我有一个基本的LinkedList实现,我想在其中迭代我的节点,并将这些节点添加到哈希集中。但是,我无法做到这一点,因为我的节点被包装在Rc中,并且我在为我的std::cell::Ref Iterator for Iter实现std::hash::hash特性时遇到了问题{ 类型项=NodeRef; fn下一步(&mut self)->选项{ 如果让Some(next)=self.next.clone(){ //设置新的self.next: 如果让一些(new_next)=next.borrow

我有一个基本的LinkedList实现,我想在其中迭代我的节点,并将这些节点添加到哈希集中。但是,我无法做到这一点,因为我的节点被包装在
Rc
中,并且我在为我的
std::cell::Ref Iterator for Iter实现
std::hash::hash
特性时遇到了问题{ 类型项=NodeRef; fn下一步(&mut self)->选项{ 如果让Some(next)=self.next.clone(){ //设置新的self.next: 如果让一些(new_next)=next.borrow().next.clone(){ self.next=Some(new_next); }否则{ self.next=无; } 返回一些(下一个); }否则{ 没有一个 } } } LinkedList的impl显示{ fn fmt(&self,w:&mut std::fmt::Formatter)->std::result::result{ 写!(w,“[”)?; 让mut node=self.head.clone(); 而让一些(n)=节点{ 写!(w,“{}”,n.borrow().data)?; node=n.borrow().next.clone(); if node.is_some(){ 写!(w,“,”)?; } } 写!(w,“]”) } } 节点的impl PartialEq{ fn eq(&self,其他:&self)->bool{ 如果ptr::eq(自身、其他){ //用于循环检测-如果节点共享相同的 //参考,他们是平等的。 返回true; } self.data==other.data&&self.next==other.next } fn ne(&self,其他:&self)->bool{ if!ptr::eq(自身、其他){ 返回true; } self.data!=other.data&&self.next==other.next } } //通过实施情商,我们承诺 //PartialEq的实现是自反的。 节点的impl Eq{ } 节点的impl std::hash::hash{ fn散列(&self,state:&mut H) 其中H:std::marker::size+Hasher { self.data.hash(状态); 如果让Some(next)=self.next.clone(){ next.borrow().hash(state); } } } ////TODO:救命!!! ////正在尝试为Ref实现哈希特性{ //fn散列(&self,state:&mut H){ //self.data.hash(状态); //如果让Some(next)=self.next.clone(){ //next.borrow().hash(state); // } // } // } LinkedList的impl PartialEq{ fn eq(&self,其他:&self)->bool{ self.head==其他.head } fn ne(&self,其他:&self)->bool{ 自个头 } } 链接列表{}的impl Eq #[cfg(测试)] 模试验{ 使用超级::*; #[测试] fn eq(){ 让mut list=LinkedList::new(); 列表。附加(1); 列表。附加(2); 列表。附加(3); 让mut list2=LinkedList::new(); 清单2.追加(1); 清单2.追加(2); 清单2.追加(3); 断言(列表,列表2); list2=LinkedList::new(); 清单2.追加(3); 断言!(列表,列表2); list=LinkedList::new(); 列表。附加(3); 断言(列表,列表2); } #[测试] fn append(){ 让mut list=LinkedList::new(); 列表。附加(1); 列表。附加(2); 列表。附加(3); 让mut list2=LinkedList::new(); 清单2.追加(1); 清单2.追加(2); 清单2.追加(3); 断言(列表,列表2); 清单2.追加(1); 断言!(列表,列表2); 列表。附加(1); 断言(列表,列表2); } //TODO:修复此测试用例! #[测试] fn hashset_iter_节点(){ 让mut list=LinkedList::new(); 列表。附加(1); 列表。附加(2); 列表。附加(3); //特性绑定为'std::cell::Ref`) //[E0277] //特性绑定为'std::cell::Ref`) //[E0277] 让mut set=HashSet::new(); //迭代节点,将每个节点添加到哈希集: 对于list.iter()中的节点{ println!(“在节点上迭代:{:?}”,节点); set.insert(&node.borrow()); } 断言(set.len(),3); } }
要将现有类型添加到哈希集中,我按照上面的注释,定义了一个新的包装类型:

pub结构HashedNode(Rc);
这样做允许我在我的
Rc
类型上实现
std::hash::hash
特性,如下所示:

HashedNode的impl std::hash::hash{ fn散列(&self,state:&mut H){ //…等等 } } 这使我能够定义哈希集并根据需要使用它:

let mut set:HashSet=HashSet::new();
注意,还需要一些其他的解决方法,比如为我的新的
HashedNode
类型实现
Eq
trait,以及实现
From
trait和
From\u node
实用方法

下面是上面示例中完成的代码:

使用std::cell::{RefCell,Ref};
使用std::fmt;
使用std::fmt::Display;
使用std::ptr;
使用std::rc::rc;
使用std::hash::{hash,Hasher};
使用std::collections::HashSet;
发布类型NodeRef=Rc;
//专门用于哈希需求,如哈希集:
pub结构HashedNode(NodeRef);
#[导出(调试)]
发布结构链接列表{
酒吧老板:选择,
}
//#[派生(散列)]
发布结构节点{
发布数据:T,
下一步:选择,
}
impl fmt::节点的调试{
fn fmt(&self,f:&mut fmt::Formatter)->fmt::Result{
写!(f,“节点{{data:{:?},下一个:{:?}}”,self.data,self.next)
}
}
impl链接列表
哪里
T:std::cmp::Eq
+std::hash::hash
+std::clone::clone
+std::cmp::PartialOrd
+std::cmp::PartialOrd
+std::fmt::Debug,
{
pub fn new()->Self{
Self{head:None}
}
发布fn追加(&mut self,新值:T){
如果让一些(tail)=self.tail(){
tail.borrow_mut().next=Some(Rc::new)(RefCell::new(Node{
数据:新的_值,
下一个:没有,
})));
}否则{