rust 正在缓存智能指针

hrysbysz  于 2022-12-04  发布在  其他
关注(0)|答案(1)|浏览(152)

如何在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
wecizke3

wecizke31#

有两个约束:

  1. HashMap需要固定大小的键值
    1.您需要使用一个特征对象,这样您的代码就可以处理任何满足特征要求的对象
    还有一个主要问题:
    1.特征对象必须由对象安全的基本特征构成,但是
  2. Sized特征不是对象安全的(对于complicatedreasons
    我 * 相信 * 解决方案是用简单的Box Package 器替换trait对象; Package 器的大小是固定的,因此HashMap可以将其用作键/值,并且装箱允许您在装箱的对象上调用trait方法。
    缺点:You'll need to define a trait that includes eq , hash and as_any , then implement said trait for all relevant concrete types, to allow it to be used as a hash key

相关问题