如何在rust中创建缓存智能指针?
因此,任何等价对象都可以作为该对象的单个示例的引用来处理,最后,我希望能够利用std::ptr::eq
进行等价性检查,而不是一直使用PartialEq
。
我想我希望能够做这样的事情:
let object = String::from("hello");
let first = One::new(object);
let second = One::new(object);
assert!(std::ptr::eq(first, second));
这是我尝试做的一个聪明的指针
use std::collections::HashMap;
use std::hash::Hash;
trait OneKeyTrait: Hash + Sized {}
static mut cache: HashMap<dyn OneKeyTrait, One<dyn OneKeyTrait>> = HashMap::new();
pub struct One<T: OneKeyTrait> {
count: usize,
value: T,
}
impl<T: OneKeyTrait> One<T> {
fn new(x: T) -> One<T> {
if cache.contains_key(&x) {
cache.get_mut(&x).count += 1;
cache.get(&x)
} else {
let one_x = One {
count: 1,
value: x,
};
cache.insert(x, one_x);
one_x
}
}
}
impl<T: OneKeyTrait> std::ops::Deref for One<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.value
}
}
impl<T: OneKeyTrait> Drop for One<T> {
fn drop(&mut self) {
let mut one_x = cache.get_mut(&self.value);
one_x.count -= 1;
if one_x.count == 0 {
cache.remove(&self.value);
}
}
}
fn main() {
let object = String::from("hello");
let first = One::new(object);
let second = One::new(object);
assert!(std::ptr::eq(first, second));
}
但它不会编译,因为
error[E0277]: the size for values of type `(dyn OneKeyTrait + 'static)` cannot be known at compilation time
--> one.rs:6:19
|
6 | static mut cache: HashMap<dyn OneKeyTrait, One<dyn OneKeyTrait>> = HashMap::new();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `(dyn OneKeyTrait + 'static)`
note: required by a bound in `HashMap`
error[E0038]: the trait `OneKeyTrait` cannot be made into an object
--> x.rs:6:48
|
6 | static mut cache: HashMap<dyn OneKeyTrait, One<dyn OneKeyTrait>> = HashMap::new();
| ^^^^^^^^^^^^^^^ `OneKeyTrait` cannot be made into an object
|
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> one.rs:4:27
|
4 | trait OneKeyTrait: Hash + Sized {}
| ----------- ^^^^^ ...because it requires `Self: Sized`
| |
| this trait cannot be made into an object...
= help: consider moving `hash` to another trait
1条答案
按热度按时间wecizke31#
有两个约束:
HashMap
需要固定大小的键值1.您需要使用一个特征对象,这样您的代码就可以处理任何满足特征要求的对象
还有一个主要问题:
1.特征对象必须由对象安全的基本特征构成,但是
Sized
特征不是对象安全的(对于complicatedreasons)我 * 相信 * 解决方案是用简单的
Box
Package 器替换trait对象; Package 器的大小是固定的,因此HashMap
可以将其用作键/值,并且装箱允许您在装箱的对象上调用trait方法。缺点:You'll need to define a trait that includes
eq
,hash
andas_any
, then implement said trait for all relevant concrete types, to allow it to be used as a hash key。