无法推断出默认的泛型类型参数

时间:2016-06-10 12:27:45

标签: generics rust default

我试图将位向量库作为练习来实现,但是在想要为泛型类型参数定义默认值时遇到了麻烦。

这是我所拥有的代码的摘录:

extern crate num;

use std::cmp::Eq;
use std::ops::{BitAnd,BitOrAssign,Index,Shl};
use num::{One,Zero,Unsigned,NumCast};

pub trait BitStorage: Sized + 
    BitAnd<Self, Output = Self> + 
    BitOrAssign<Self> + 
    Shl<Self, Output = Self> + 
    Eq + Zero + One + Unsigned + NumCast + Copy {}

impl<S> BitStorage for S where S: Sized + 
    BitAnd<S, Output = S> + 
    BitOrAssign<S> + 
    Shl<S, Output = S> + 
    Eq + Zero + One + Unsigned + NumCast + Copy {}

pub struct BitVector<S: BitStorage = usize> {
    data: Vec<S>,
    capacity: usize
}

impl<S: BitStorage> BitVector<S> {
    pub fn with_capacity(capacity: usize) -> BitVector<S> {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector { data: vec![S::zero(); len], capacity: capacity }
    }

    //...
}

我想按如下方式使用它:

let vec = BitVector::with_capacity(1024);

但是我收到编译错误:

  

lib.rs:225:24:225:48错误:无法推断出有关_的足够类型信息;需要输入注释或通用参数绑定[E0282]
  lib.rs:225让vec_1000 = BitVector :: with_capacity(1000);
                                    ^ ~~~~~~~~~~~~~~~~~~~~~~~
  lib.rs:225:24:225:48 help:运行rustc --explain E0282查看详细说明

要为代码提供更多上下文,BitStorage目前有效的类型包括(但不限于*)u8u16u32,{ {1}}和u64

(*)如果您实现该类型的所有特征,我认为您可以编写自定义usize实现(仅作为示例)。

在使用Google搜索问题后,我发现RFC 213似乎不是be stable yet。但另一方面HashMap当前处于稳定状态是使用默认值,所以它应该正常工作,对吗?

1 个答案:

答案 0 :(得分:4)

对默认类型参数的支持仍然有限,但在某些情况下可以使用。当使用带有默认类型参数的struct来指定变量的类型时,默认的类型参数用于定义变量的类型:

// the type of vec is BitVector<usize>, so the type of
// BitVector::with_capacity(1024) is correctly inferred
let vec: BitVector = BitVector::with_capacity(1024);
  

然而另一方面HashMap目前处于稳定状态是使用默认值,所以它应该正常工作,对吗?

查看HashMap源代码,我们可以看到方法newwith_capacity使用RandomState S参数实现,而不是取决于HashMap中的默认类型参数。所有其他方法都在S上实现为通用,包括其他“构造函数”方法,如with_hasher

你可以写类似的东西:

impl BitVector<usize> {
    pub fn default_with_capacity(capacity: usize) -> BitVector<usize> {
        // type is inferred
        Self::with_capacity(capacity)
    }
}

impl<S: BitStorage> BitVector<S> {
    pub fn with_capacity(capacity: usize) -> BitVector<S> {
        let len = (capacity / (std::mem::size_of::<S>() * 8)) + 1;
        BitVector {
            data: vec![S::zero(); len],
            capacity: capacity,
        }
    }

    // ...
}

// create with "default" BitStore
let vec = BitVector::default_with_capacity(1024);
// specify BitStore
let vec = BitVector::<u32>::with_capacity(1024);