Iterating over a set of objects with a trait

I am trying to iterate over either a set of function pointers which return objects which implement a trait. Or failing this, the objects themselves directly.

I have something like this:

Neither of which work because I cannot type the Vec properly. I've tried a variety of different mechanisms, including Box, adding impl Trait at various points. But I cannot get this to work.

Any help gratefully received.

Edit: I want to iterate over the objects, calling objects on the trait, till I find one which "works" (matches a pattern in this case). I thought pointers to the constructors would work better so that I do not have to construct objects that I will not use all of.

What you're trying to do is not possible.

Vec requires all items to have the same type and same size, but each type implementing a trait could have any size, from zero to 2^63, so there's no way of putting them in directly.

So to unify types and sizes in the Vec, you'd have to use trait objects, i.e. an abstract type. Wrapping each item in Box to get Box<dyn Trait>.

However, once the type is "erased" via box, you can't use Self in the trait, because information what Self was has already been erased and callers of that function will have no idea what to do with it.

If your trait didn't use Self, then you could make Vec<Box<dyn Trait>>. You could also change your trait to return Box<dyn Anothertrait> instead of Self.

I have tried something like this...

which also fails. I need two traits?

Ah, sorry. Trait objects also require that you use &self in the methods (so that there is a pointer from which the program can read what type it is). So HasDefault just won't work as a trait object.

You can use array of function pointers to make objects of various types. You can use another trait what has methods with &self:

#[derive(Debug)]
struct DefaultOne;

#[derive(Debug)]
struct DefaultTwo;

pub fn main() {
    let ctors = vec![(|| Box::new(DefaultOne)) as fn() -> Box<dyn std::fmt::Debug>, || Box::new(DefaultTwo)];
    let objs = vec![Box::new(DefaultOne) as Box<dyn std::fmt::Debug>, Box::new(DefaultTwo)];
}   

Okay. I will use a different idiom instead -- I actually know all the values that I want to iterate over at compile time, so I've moved my for loop body into a new function, then call these repeatedly in a big or boolean expression to get short-circuiting.

Probably simpler, as it happens.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.