哈希特征不适用于枚举中的 Rc<RefCell<T>>
Hash trait does not work for Rc<RefCell<T>> in enum
我定义了一个结构 MyData
并手动实现了 PartialEq
和 Hash
特征。
我定义了一个枚举,其中包括 Rc<MyData>
和 Rc<RefCell<MyData>>
。
我想为枚举派生 PartialEq
和 Hash
,但失败了:
PartialEq
和 Hash
都适用于 Rc<MyData>
;
PartialEq
也适用于 Rc<RefCell<MyData>>
;
- 但是
Hash
不适用于 Rc<RefCell<MyData>>
!
我有 2 个问题:
为什么?为什么只有 Hash
不适用于 Rc<RefCell<MyData>>
?
如何解决?
我无法为 Rc<RefCell<MyData>>
实施 Hash
。经过四处搜索,我找到了一种方法:定义一个新的包装器结构,比如 struct RRWrapper<T> (Rc<RefCell<T>>)
,然后为这个 RRWrapper
实现 Hash
。但这会带来很多代码。有惯用的方法吗?我认为这是一般用法。
提前致谢,
吴
PS:在我程序的真实代码中,枚举中只有Rc<RefCell<MyData>>
而没有Rc<MyData>
。我把 Rc<MyData>
放在这里只是为了比较。
PS2:在我程序的真实代码中,enum中有多个Rc<RefCell<T>>
。
原始源代码:
use std::rc::Rc;
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
struct MyData {
i: i64,
}
impl Hash for MyData {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash(state);
}
}
impl PartialEq for MyData {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
#[derive(PartialEq, Hash)]
enum MyEnum {
INT(i64),
STR(String),
MYDATA1(Rc<MyData>), // OK both
MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
}
fn main() {
}
错误:
20 | #[derive(PartialEq, Hash)]
| ---- in this derive macro expansion
...
25 | MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
| ^^^^^^^^^^^^^^^^^^^ the trait `Hash` is not implemented for `RefCell<MyData>`
|
= note: required because of the requirements on the impl of `Hash` for `Rc<RefCell<MyData>>`
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
struct RRWrapper
的源代码:
#[derive(Debug, PartialEq, Eq)]
pub struct RRWrapper<T: Hash+PartialEq+Eq>(Rc<RefCell<T>>);
impl<T: Hash+PartialEq+Eq> Deref for RRWrapper<T> {
type Target = Rc<RefCell<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Hash+PartialEq+Eq> Hash for RRWrapper<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.borrow().hash(state);
}
}
impl<T: Hash+PartialEq+Eq> Clone for RRWrapper<T> {
fn clone(&self) -> Self {
RRWrapper(self.0.clone())
}
}
impl<T: Hash+PartialEq+Eq> RRWrapper<T> {
pub fn new(inner: T) -> Self {
RRWrapper(Rc::new(RefCell::new(inner)))
}
}
Why? Why only the Hash does not work only for Rc<RefCell>?
如果您考虑一下,Hash
没有为 RefCell
实现是有道理的。由于它是对内部可变性的抽象,那么可能改变的东西的散列是什么?一般来说,可变的东西不适合作为 Hash
对象工作。
How to fix it?
和你一样。对你真正想要的负责。为包装器实现它。
我定义了一个结构 MyData
并手动实现了 PartialEq
和 Hash
特征。
我定义了一个枚举,其中包括 Rc<MyData>
和 Rc<RefCell<MyData>>
。
我想为枚举派生 PartialEq
和 Hash
,但失败了:
PartialEq
和Hash
都适用于Rc<MyData>
;PartialEq
也适用于Rc<RefCell<MyData>>
;- 但是
Hash
不适用于Rc<RefCell<MyData>>
!
我有 2 个问题:
为什么?为什么只有
Hash
不适用于Rc<RefCell<MyData>>
?如何解决?
我无法为
Rc<RefCell<MyData>>
实施Hash
。经过四处搜索,我找到了一种方法:定义一个新的包装器结构,比如struct RRWrapper<T> (Rc<RefCell<T>>)
,然后为这个RRWrapper
实现Hash
。但这会带来很多代码。有惯用的方法吗?我认为这是一般用法。
提前致谢,
吴
PS:在我程序的真实代码中,枚举中只有Rc<RefCell<MyData>>
而没有Rc<MyData>
。我把 Rc<MyData>
放在这里只是为了比较。
PS2:在我程序的真实代码中,enum中有多个Rc<RefCell<T>>
。
原始源代码:
use std::rc::Rc;
use std::cell::RefCell;
use std::hash::{Hash, Hasher};
struct MyData {
i: i64,
}
impl Hash for MyData {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hash(state);
}
}
impl PartialEq for MyData {
fn eq(&self, other: &Self) -> bool {
self == other
}
}
#[derive(PartialEq, Hash)]
enum MyEnum {
INT(i64),
STR(String),
MYDATA1(Rc<MyData>), // OK both
MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
}
fn main() {
}
错误:
20 | #[derive(PartialEq, Hash)]
| ---- in this derive macro expansion
...
25 | MYDATA2(Rc<RefCell<MyData>>), // OK for PartialEq but not for Hash
| ^^^^^^^^^^^^^^^^^^^ the trait `Hash` is not implemented for `RefCell<MyData>`
|
= note: required because of the requirements on the impl of `Hash` for `Rc<RefCell<MyData>>`
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
struct RRWrapper
的源代码:
#[derive(Debug, PartialEq, Eq)]
pub struct RRWrapper<T: Hash+PartialEq+Eq>(Rc<RefCell<T>>);
impl<T: Hash+PartialEq+Eq> Deref for RRWrapper<T> {
type Target = Rc<RefCell<T>>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: Hash+PartialEq+Eq> Hash for RRWrapper<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.borrow().hash(state);
}
}
impl<T: Hash+PartialEq+Eq> Clone for RRWrapper<T> {
fn clone(&self) -> Self {
RRWrapper(self.0.clone())
}
}
impl<T: Hash+PartialEq+Eq> RRWrapper<T> {
pub fn new(inner: T) -> Self {
RRWrapper(Rc::new(RefCell::new(inner)))
}
}
Why? Why only the Hash does not work only for Rc<RefCell>?
如果您考虑一下,Hash
没有为 RefCell
实现是有道理的。由于它是对内部可变性的抽象,那么可能改变的东西的散列是什么?一般来说,可变的东西不适合作为 Hash
对象工作。
How to fix it?
和你一样。对你真正想要的负责。为包装器实现它。