如何在Rust中的外部数据类型上实现std::hash::hash特性?
我有一个基本的LinkedList实现,我想在其中迭代我的节点,并将这些节点添加到哈希集中。但是,我无法做到这一点,因为我的节点被包装在如何在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
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{
数据:新的_值,
下一个:没有,
})));
}否则{