How to have a vec of Boxes which implement 2 traits? [duplicate]
Asked Answered
S

2

8

In rust I would like to have a vec containing items which implement 2 traits. However when I try to implement it like so, I get the error only auto traits can be used as additional traits in a trait object:

let mut v : Vec<Box<dyn MyTrait + std::fmt::Display>> = Vec::new();

FairPlay, I read the error message in full and defined a Trait which combines the two:

pub trait FormattableDoer: std::fmt::Display + MyTrait{}

The have a Vec of Boxes to that:

let mut v: Vec<Box<dyn FormattableDoer>> = Vec::new();

However the compiler can't seem to detect that my struct has implemented those things separately and I get the error the trait bound MyStruct: FormattableDoer is not satisfied.

I read about using a trait alias, but that's not in stable so I'd rather not use it.

Is this possible in rust? It seems like a common thing to want to do and I'm surprised that the answer isn't simple (or maybe it is and I have missed it!). I'm also thinking that maybe I have approached the problem all wrong and I'm attempting to do something in an 'non rusty' way. If that's the case, what is the preferred way of having a vector of things which are displayable and have some other trait?

Playground with a MWE and a use case.

Solarism answered 17/4, 2022 at 20:21 Comment(0)
P
9

You're almost there. You need a marker trait that implements both parents, as you've already done

pub trait FormattableDoer: std::fmt::Display + MyTrait {}

Then you need a blanket implementation which takes those two traits to your new trait.

impl<T: std::fmt::Display + MyTrait> FormattableDoer for T {}

Now everything that implements std::fmt::Display and MyTrait will implement FormattableDoer automatically, and since FormattableDoer is a single trait, it can be used as a trait object.

Then just use Box<dyn FormattableDoer> like you've already tried.

Phylum answered 17/4, 2022 at 20:24 Comment(0)
A
3

You still need to implement FormattableDoer for your struct. In the playground you posted, you're not doing that. Simply add

impl FormattableDoer for MyStruct {}

and you should be all done.

No user-defined traits are auto-implemented, even if they contain no methods or associated types.

Arabic answered 17/4, 2022 at 20:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.