2016-06-10 2 views
5

Я пытаюсь реализовать библиотеку бит-вектора в качестве упражнения, однако у меня возникают проблемы, когда вы хотите определить значение по умолчанию для параметра общего типа.Default generic type parameter не может быть выведено

Это отрывок кода у меня есть:

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, u64 и usize.

(*) Я думаю, что вы можете написать обычную реализацию 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 исходный код, мы можем см., что методы new и with_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); 
Смежные вопросы