I'm trying to implement a Bit Vector library as an exercise, however I'm hitting trouble when wanting to define a default value for a generic type parameter.
This is an excerpt of the code I have:
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 }
}
//...
}
And I want to use it as follows:
let vec = BitVector::with_capacity(1024);
However I get a compiler error:
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: runrustc --explain E0282
to see a detailed explanation
To give a little more context to the code, currently valid types for BitStorage
include (but are not limited to*) u8
, u16
, u32
, u64
and usize
.
(*) I think you could write a custom u128
implementation (just as example) if you implement all the traits for that type.
After googling about the issue I found RFC 213 which does not seem to be stable yet. However on the other hand HashMap currently on stable is using default values, so it should be working, right?
The support for default type parameters is still limited, but can be used in some cases. When a struct
with default type parameter is used to specify the type of a variable, the default type parameter is used to define the type of the variable:
// 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?
Looking at the HashMap
source code, we can see that the methods new
and with_capacity
are implemented with RandomState
for the S
parameter and does not depend on the default type parameter in HashMap
. All other methods are implemented as generic on S
, including other "constructor" methods like with_hasher
.
You can write something similar:
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With