I'd like to create a generic struct that uses a generic newtype to index. Ideally it would look something like this:
use std::marker::PhantomData;
struct Foo<I, T> {
bar: Vec<T>,
_marker: PhantomData<I>,
}
impl <I, T> Foo<I, T> {
fn new(v: Vec<T>) -> Foo<I, T> {
Foo {
bar: v,
_marker: PhantomData,
}
}
fn get(&self, index: &I) -> &T {
// let index: usize = index.0; // I want to use this line.
let index = 0; // This line is incorrect, but compiles.
&self.bar[index]
}
}
The generic newtype is guaranteed to be usize, like this:
pub struct Baz(pub usize);
pub struct Qux(pub usize);
This compiles and correctly enforces type checking.
fn main() {
let index_b = Baz(1);
let index_q = Qux(1);
let data: Foo<Baz, i32> = Foo::new(vec![1,2,3]);
assert_eq!(*data.get(&index_b), 2);
// Type Checking Violation - Does not compile.
// assert_eq!(*data.get(&index_q), 2);
}
However notice that the get() function is incorrect. How do you tell the compiler that I is a usize so the get() function will be correct?
You'll need to use some kind of trait. There's no existing constraint to verify that an
Iis actually aSomeType(T)to know thatindex.0is valid.My immediate thought would be to implement
Intoon your newtype:And you would pass
indexby value intoget:Other options would be
DereforAsRefor it may make sense to make your ownFooIndextrait.For
AsRef:And
Deref: