I wrote the bellow code.
My intention is to store a vec of generic struct (Metric) and retrieve each item afterwards. If possible with the original type they were created with.
Below code works fine. But I would like the get_mes() method to return T from Metric field mes and not a String.
And to be honest I don't know how to get out of these errors.
I have the feelings that it is not possible to return the original T type. Can you confirm ?
Is there a way to achieve what I would like to do ?
It is not possible to automatically implement Debug for all types that implement Measure because that would let you implement Debug on a foreign type by implementing Measure for that foreign type.
Unfortunately, I need to define T (e.g. usize) and then I can not store Metrics using mes from other types unless if I'm wrong.
Pushing the second metrics will end up with:
error[E0277]: the trait bound `Metric<{float}>: Measure<usize>` is not satisfied
--> src/main.rs:31:16
|
31 | data.push(Box::new(Metric {
| ________________^
32 | | name: String::from("toto"),
33 | | mes: 0.2,
34 | | }));
| |_______^ the trait `Measure<usize>` is not implemented for `Metric<{float}>`
|
= help: the following implementations were found:
<Metric<T> as Measure<T>>
= note: required for the cast to the object type `dyn Measure<usize>`
Given a dyn SomeTypeOfMeasure that you can call methods on, the methods must be able to be type checked. So for example, method get_mes(&self) -> T must have a concrete type for the T. Consider this:
fn f(m: &dyn SomeTypeOfMeasure) {
// Compiler needs to type check this with only the constraints in the declaration
// Namely: `*m` is a `dyn SomeTypeOfMeasure`
let x: usize = m.get_mes();
}
So whether you have Measure or Measure<T> or Measure<AsssociatedType = T>, the T is going to have to be concrete for any dyn [...].
You may need to be less generic by deciding what the full set of possible types for get_mes are and returning an enum, or picking a "good enough for anyone" type and having that be the return type of get_mes, etc.
You can keep being generic if you do something like this:
// Whatever trait is sufficient should take the place of `Display`
fn get_mes(&self) -> Box<dyn Display>;
Which works because Box<dyn Trait> is a concrete type. But you won't be getting the original types back out.