2016-06-10 187 views
5

我试图实现一个位矢量库作为练习,但是当我想要定义一个泛型类型参数的默认值时遇到了麻烦。默认泛型类型参数不能推断

这是代码的摘录,我有:

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 error: unable to infer enough type information about _ ; type annotations or generic parameter binding required [E0282]
lib.rs:225 let vec_1000 = BitVector::with_capacity(1000);
^~~~~~~~~~~~~~~~~~~~~~~~
lib.rs:225:24: 225:48 help: run rustc --explain E0282 to see a detailed explanation

为了给代码提供更多的上下文,BitStorage的当前有效类型包括(但不限于* )u8,u16,u32,u64usize。 (*)我认为你可以编写一个自定义的u128实现(就像例子),如果你实现了该类型的所有特征。

关于这个问题的谷歌搜索后,我发现RFC 213似乎并不be stable yet。但另一方面HashMap目前稳定是使用默认值,所以它应该工作,对不对?

回答

3

默认类型参数的支持仍然有限,但可以在某些情况下使用。当与默认类型参数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); 

However on the other hand HashMap currently on stable is using default values, so it should be working, right?

综观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);