The trait cannot be made into an object

code first as below,

#[derive(Debug)]
struct Element<T>{value:T}

trait ElementTrait {
    fn get(&self)->Self;
}

impl<T> ElementTrait for Element<T> {
    fn get(&self)->Self {
        *self
    }
}

fn main(){
    let a:Box<dyn ElementTrait> = Box::new(Element{value:1.1});
    let b:Box<dyn ElementTrait> =Box::new(Element{value:1});
    let c = vec![a, b];

    for each in c.iter(){
        println!("{:?}", each.get());
    }
}

test it and warns: the trait cannot be made into an object consider moving get to another trait.

the background: I wannt to put different types of value into a vec via Box, and then iter this vec, get each value from its original struct "value", finally print this value (or get this value and do something else.)

I understand the problem but don't know how to modify the code,
also check the downcast, but it seems don't help,

What you are trying to do doesn't make much sense: you can't get different concrete types out in a uniform loop. If you need to debug-print the inner values, then you can just coerce them to dyn Debug:

#[derive(Debug)]
struct Element<T> {
    value: T,
}

fn main() {
    let a: Box<dyn Debug> = Box::new(Element { value: 1.1 });
    let b: Box<dyn Debug> = Box::new(Element { value: 1 });
    let c = vec![a, b];

    for item in &c {
        println!("{:?}", item);
    }
}

If you need them to do something else, you'll need to coerce them to a different trait object.

It does work, but again, you can't make a loop have different types upon different iterations:

fn main() {
    let a: Box<dyn Any> = Box::new(Element { value: 1.1_f64 });
    let b: Box<dyn Any> = Box::new(Element { value: 1_u32 });
    let c = vec![a, b];

    for item in &c {
        if let Some(item) = item.downcast_ref::<Element<u32>>() {
            println!("item: u32 = {}", item.value);
        } else if let Some(item) = item.downcast_ref::<Element<f64>>() {
            println!("item: f64 = {}", item.value);
        } else {
            println!("item is neither u32 nor f64");
        }
    }
}

However, this is an anti-pattern and it's pretty much non-idiomatic. If you want to represent a fixed set of values, you should likely create an enum instead:

#[derive(Debug)]
enum Element {
    Int(i64),
    Float(f64),
}

fn main() {
    let a = Element::Float(1.1);
    let b = Element::Int(1);
    let c = vec![a, b];

    for item in &c {
        println!("{:?}", item);
    }
}
5 Likes

perfect and highly appreciated for your great helppppppppp!!!!!!!

it's so great......

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.