How do I get a vector of structs sharing the same trait method, but with different output types, to run?

Is it even possible to do so or would I need to take a very different approach?

Calculate::Output must be the same concrete type (which would include some pointer type to a trait object) for every element in your vector, because dyn Calculate<Output=i32> is not the same type as dyn Calculate<Output=f64> and vectors are homogenous, so they can only store elements that all have the same type.

2 Likes

If all of the output types have a common interface, like Display, you can define a helper trait to make this work:

pub trait Calculate {
    type Output: Display;

    fn calculate(&self) -> Self::Output;
}

trait CalcForDisplay {
    fn calc_for_display(&self)->Box<dyn Display + '_>;
}

impl<T:Calculate + ?Sized> CalcForDisplay for T {
    fn calc_for_display(&self)->Box<dyn Display + '_> {
        Box::new(self.calculate())
    }
}
2 Likes

@2e71828 's method is better!

This is mine ( with std::any):

pub trait Calculate {
    fn calculate(&self) -> Box<dyn Any>;
    fn display(&self) {
        let ans = self.calculate();
        if (*ans).type_id() == TypeId::of::<f64>() {
            println!("{}", ans.downcast::<f64>().unwrap());
        } else if (*ans).type_id() == TypeId::of::<i32>() {
            println!("{}", ans.downcast::<i32>().unwrap());
        } else {
            unreachable!();
        }
    }
}
1 Like

You can avoid the double-checking and unwraps here by using if let:

        if let Some(x) = ans.downcast_ref::<f64>() {
            println!("{}", x);
        } else if let Some(x) = ans.downcast_ref::<i32>() {
            println!("{}", x);
        }
3 Likes