[英]Rust struct can't replace trait in HashMap
I'm trying to create a HashMap
containing a known value for a specific input. 我正在尝试创建一个包含特定输入的已知值的HashMap
。 This input can accept multiple types, as long as they implement a certain trait. 此输入可以接受多种类型,只要它们实现某种特征即可。 In this case, however, only a certain type is given, which Rust doesn't like. 但是,在这种情况下,只给出了某种类型,Rust不喜欢这种类型。
Is there any way to "convert" a struct into a trait, or otherwise fix this issue? 有没有办法将结构“转换”为特征,或以其他方式解决这个问题?
#![allow(unused)]
use std::collections::HashMap;
use std::hash::*;
trait Element: Eq + PartialEq + Hash {}
trait Reaction<T: Element> {}
#[derive(Eq, Hash, PartialEq)]
struct Ion {
charge: u16
}
impl Element for Ion {}
#[derive(Eq, Hash, PartialEq)]
struct RedoxReaction<T: Element> { left: T }
impl<T: Element> Reaction<T> for RedoxReaction<T> {}
fn get_sep_database<T: Element>() -> HashMap<RedoxReaction<T>, f32> {
let mut map: HashMap<RedoxReaction<T>, f32> = HashMap::new();
let reaction = RedoxReaction {
left: Ion {
charge: 1
}
};
// note: expected type `RedoxReaction<T>`
// found type `RedoxReaction<Ion>`
map.insert(reaction, 0.000 as f32);
return map;
}
fn main() {
let db = get_sep_database();
let reaction = RedoxReaction {
left: Ion {
charge: 1
}
};
// expected this to be 0.000
let sep = db.get(&reaction);
}
The standard solution to this problem would be to use trait objects instead of generics. 这个问题的标准解决方案是使用特征对象而不是泛型。 Specifically, RedoxReaction
would be defined as: 具体来说, RedoxReaction
将定义为:
#[derive(Eq, Hash, PartialEq)]
struct RedoxReaction { left: Box<Element> }
However, that doesn't work here because neither PartialEq
, Eq
nor Hash
are object safe . 但是,这在这里PartialEq
,因为PartialEq
, Eq
和Hash
都不是对象安全的 。 Indeed, it doesn't make a lot of sense to ask if two Elements
are equal when one of them is an Ion
and the other is a Photon
. 实际上,当其中一个是Ion
而另一个是Photon
时,询问两个Elements
是否相等并没有多大意义。
I would instead recommend that you consider using an enum for your elements. 我建议您考虑为元素使用枚举 。 All your elements would have the same type (the enum Element
), and object safety would not be an issue. 所有元素都具有相同的类型(枚举Element
),对象安全性不会成为问题。
I eventually solved this problem by using the hash of the Reaction
as the key of the HashMap
with the following function: 我最终通过使用Reaction
的哈希作为HashMap
的键来解决这个问题,具有以下功能:
use std::collections::hash_map::DefaultHasher;
use std::hash::*;
fn reaction_to_hash<E: Element>(reaction: &Reaction<E>) -> u64 {
let mut s = DefaultHasher::new();
reaction.hash(&mut s);
s.finish()
}
Then you can use map.insert(reaction_to_hash(&reaction), <value>)
to store the values, and map.get(& reaction_to_hash(&reaction))
to retrieve the value. 然后您可以使用map.insert(reaction_to_hash(&reaction), <value>)
来存储值,并使用map.get(& reaction_to_hash(&reaction))
来检索值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.