如何在一个Box中放置一个std :: hash :: Hasher?

时间:2017-07-24 20:00:11

标签: rust

我的数据结构如下所示:

pub struct X<K> {
    hasher: Box<std::hash::Hasher>,
    phantom: std::marker::PhantomData<K>,
}

使用如下:

impl<K: std::hash::Hash> Trait<K> for X<K> {
    fn function(&mut self, key: &K) -> usize {
        ...
        key.hash(&mut *self.hasher);
        ...
    }
}

我在夜间收到以下编译错误:

  

std::hash::Hasher

未实施特征std::boxed::Box<std::hash::Hasher + 'static>

另一种方法是使用key.hash(self.hasher.deref_mut()),这会触发以下错误:

  

std::hash::Hasher + 'static在编译时没有已知的常量

这两个错误都在hash来电中。我觉得奇怪的是std::hash::Hasher没有为Box实现,但我不知道这是不是为了保护我免受自己伤害。除此之外,考虑到deref_mut 应该是一个固定大小的结构,Box错误在编译时会抱怨已知大小,这似乎很奇怪。

我知道解决这个问题的一种方法是使用模板参数,但我避免这样做,因为X将用于其他不需要参数的数据结构中,这意味着我必须传递一个不必要的参数。这似乎是HashMap采用的方法,因为它使用RandomState模板参数,但我希望尽可能避免这种情况。

1 个答案:

答案 0 :(得分:2)

  

我觉得很奇怪std::hash::Hasher

没有实现Box

我认为你的意思是Box<T> where T: std::hash::Hasher。我不知道为什么它不会实现,但可能只是因为还没有人。

  

deref_mut错误抱怨在编译时已知大小

,这似乎很奇怪

问题是泛型类型H具有隐式Sized绑定(默认情况下一切都是这样):

fn hash<H>(&self, state: &mut H)
    where
        H: Hasher;

你需要它说:

fn hash<H>(&self, state: &mut H)
    where
        H: ?Sized + Hasher;

同样,我认为没有任何理由不能改变这样做,这很可能是没有人需要它。

您可以添加新类型来解决此问题:

use std::hash;

pub struct X<K> {
    hasher: BoxedHasher,
    phantom: std::marker::PhantomData<K>,
}

struct BoxedHasher(Box<hash::Hasher>);

impl hash::Hasher for BoxedHasher {
    fn finish(&self) -> u64 {
        self.0.finish()
    }

    fn write(&mut self, bytes: &[u8]) {
        self.0.write(bytes)
    }
}

impl<K> X<K>
where
    K: hash::Hash,
{
    fn function(&mut self, key: &K) -> usize {
        key.hash(&mut self.hasher);
        0
    }
}