#Finding a struct implementing a Trait

8 messages · Page 1 of 1 (latest)

fallow hornet
#

So I know I'm asking for something impossible here, I really need an alternative to this approach.
I have a struct containing a Vec<Box<dyn Interface>> where each Interface is reading data from some source.
Some, but not all Interfaces also impl Clock where Clock provides a timestamp used to sync the other interfaces (this is vaguely similar to GStreamer's clock system.)
I want to be able to automatically find the first struct in my vec that implements Clock and store it separately so that I can request the timestamp directly from it.
One approach I don't like is having a provides_clock method inside Interface.

winter ruin
#

I think

fn func<'a>(v: &'a Vec<Box<dyn Any>>) -> Option<&'a Box<dyn Clock>> {
    v.iter().filter_map(|x| x.downcast_ref()).next()
}
``` would do this, but the problem is you'd need to cast a `Box<dyn Clock>` up to `Box<dyn Any>`, which I'm not sure is possible
fallow hornet
winter ruin
#

?play

use std::any::Any;
struct T;
struct T2;
trait Clock {}
trait Interface {}
impl Interface for T {}
impl Clock for T {}
impl Interface for T2 {}

fn func<'a>(v: &dyn Any) -> Option<&Box<dyn Clock>> {
    v.downcast_ref()
}

fn main() {
    let v = Box::new(T) as Box<dyn Clock>;
    let v2 = Box::new(T2) as Box<dyn Interface>;
    println!("{}", func(&v as &dyn Any).is_some()); // is a Box<dyn Clock>
    println!("{}", func(&v2 as &dyn Any).is_some());  // isn't a Box<dyn Clock>
}
timid shadowBOT
#
true
false
winter ruin
#

You can downcast to a boxed trait object if the original value was a boxed trait object

fallow hornet
#

?play

use std::any::Any;
struct Foo;
struct Bar;
trait Clock {}
trait Interface {}
impl Interface for Foo {}
impl Interface for Bar {}
impl Clock for Bar {}

fn main() {
  let interfaces: Vec<Box<dyn Interface>> = vec![
    Box::new(Foo),
    Box::new(Bar),
  ];
  
  for interface in &interfaces {
    let interface = interface as &dyn Any;
    println!("{}", interface.is::<dyn Clock>());
  }
}
timid shadowBOT
#
error[E0277]: the size for values of type `dyn Clock` cannot be known at compilation time
  --> src/main.rs:18:30
   |
18 |     println!("{}", interface.is::<dyn Clock>());
   |                              ^^ doesn't have a size known at compile-time
   |
   = help: the trait `Sized` is not implemented for `dyn Clock`
note: required by a bound in `<(dyn Any + 'static)>::is`

For more information about this error, try `rustc --explain E0277`.