【问题标题】:Default generic type parameter cannot be inferred无法推断默认泛型类型参数
【发布时间】:2016-10-11 10:12:48
【问题描述】:

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

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

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 的当前有效类型包括(但不限于*)u8u16u32u64usize

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

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

【问题讨论】:

    标签: generics rust default


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      • 1970-01-01
      • 2021-11-06
      • 2021-12-22
      • 1970-01-01
      • 2016-12-05
      相关资源
      最近更新 更多