简体   繁体   中英

Rust return a generic struct which the generic type is NOT known in advance by the caller

I am trying to achieve something like below:

#[derive(Debug)]
struct Bar<T> {
    val: Option<T>,
    cfg: HashMap<String, String>
}

impl<T> Bar<T> {
    pub fn new(val: T) -> Self {
        Self {val: Some(val), cfg: "hello".to_string()}
    }
}

trait Foo {
    // The conversion could be u8 -> f32, reshape the vector etc.
    fn converter<V: AsRef<[u8]>>(&self, input: V, p: String) -> Bar<T>;
}

So base on the different p: String being passed to the fn converter along with the Bar.cfg , it tries to convert the input: AsRef<[u8]> to a generic Bar<T> .

How should i approach this properly?

Use an associated type in your trait:

#[derive(Debug)]
struct Bar<T> {
    val: Option<T>,
    cfg: String
}

impl<T> Bar<T> {
    pub fn new(val: T) -> Self {
        Self {val: Some(val), cfg: "hello".to_string()}
    }
}

trait Foo {
    type DataType;
    
    fn converter<V: AsRef<[u8]>>(&self, p: String, input: V) -> Self::DataType;
}

Playground

Using your impl as example:

impl<T> Foo for Bar<T> {
    type DataType = Bar<Vec<f32>>;
    
    fn converter<V: AsRef<[u8]>>(&self, p: String, input: V) -> Self::DataType {
        const NORM_SCALE: f32 = 1. / 255.;
        let v32 = input.as_ref()
            .into_iter()
            .map(|x| (*x as f32) * NORM_SCALE)
            .collect::<Vec<f32>>();
            
        Bar::new(v32)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM