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
I
is actually aSomeType(T)
to know thatindex.0
is valid.My immediate thought would be to implement
Into
on your newtype:And you would pass
index
by value intoget
:Other options would be
Deref
orAsRef
or it may make sense to make your ownFooIndex
trait.For
AsRef
:And
Deref
: