getter
вызывает черты для извлечения универсального c векторного типа:
fn getter<T>(sin: &str) -> Result<Vec<T>, Error> where T: GenVecStruct
Я ожидаю, что компилятору не будет важен закомментированный код (строка 37) в обработчике ниже, так как отлично работает со строками 42, 43 и 44 **.
33 fn process<F>(input: &InType, mut callback: F) where F: FnMut(OutType), {
34 if let Ok(data) = getter("two B") {
35 match input {
36 InType::SomeInA => for v in data { callback(OutType::OutA(v)); }
37 // InType::SomeInB => for v in data { callback(OutType::OutB(v)); },
38 _ => (),
39 };
40 }
41
42 callback(OutType::OutA(A{a:1})); //No problem here
43 callback(OutType::OutB(B{b:1.})); //No problem here
44 callback(OutType::Note); //No problem here either
45 }
Компиляция с L37 выдает следующую ошибку:
error[E0308]: mismatched types
--> src/main.rs:37:71
|
37 | InType::SomeInB => for v in data { callback(OutType::OutB(v)); },
| ^ expected struct `B`, found struct `A`
Вопросы:
- Точные рассуждения: если
getter
производит обобщенный c Vec<T>
, следующее соответствие требует дополнительной информации о типе. - Как использовать дженерики, как лучше добавить дополнительную информацию о типе в
processor
? (макросы - в худшем случае)
Полный пример :
pub enum Error {E1,}
pub trait GenVecStruct where Self: Sized,
{
fn to_vec_of_t(s: &str) -> Result<Vec<Self>, Error>;
}
enum InType { SomeInA, SomeInB, }
enum OutType { OutA(A), OutB(B), OutE(Error), Note,}
struct A { a: i32, }
struct B { b: f64, }
impl GenVecStruct for A {
fn to_vec_of_t(_s: &str) -> Result<Vec<A>, Error> {
Ok(vec![A { a: 1 }, A { a: 2 }, A { a: 3 }])
}
}
impl GenVecStruct for B {
fn to_vec_of_t(_s: &str) -> Result<Vec<B>, Error> {
Ok(vec![B { b: 9. }, B { b: 8. }, B { b: 6. }])
}
}
fn getter<T>(sin: &str) -> Result<Vec<T>, Error> where T: GenVecStruct,
{
match T::to_vec_of_t(sin) {
Ok(r) => Ok(r),
Err(_) => Err(Error::E1),
}
}
fn process<F>(input: &InType, mut callback: F) where F: FnMut(OutType),
{
if let Ok(data) = getter("two B") {
match input {
InType::SomeInA => {
for v in data {
callback(OutType::OutA(v));
}
}
fn process<F>(input: &InType, mut callback: F) where F: FnMut(OutType),
{
if let Ok(data) = getter("two B") {
match input {
InType::SomeInA => for v in data{ callback(OutType::OutA(v)); },
// InType::SomeInB => for v in data{ callback(OutType::OutB(v)); },
_ => (),
};
};
callback(OutType::OutA(A { a: 1 })); //No problem here
callback(OutType::OutB(B { b: 1. })); //No problem here
callback(OutType::Note); //No problem here either
}
fn main() {
let v = InType::SomeInB;
process(&v, |p| {
match p {
OutType::OutA(_) => println!("someIn A"),
OutType::OutB(_) => println!("someIn B"),
OutType::OutE(_) => println!("err"),
OutType::Note => println!("Note"),
};
});
}