Skip to content
Snippets Groups Projects
Select Git revision
  • 519c22ed93c4543dbc246ab88e92580ecd54f5ac
  • master default
2 results

startup_stm32f40xx.s

Blame
  • trait_objects.rs 2.12 KiB
    // a struct with generics
    // a trait for double
    
    use std::fmt::Debug;
    
    #[derive(Debug)]
    struct P<T> {
        x: T,
        y: T,
    }
    
    // Debug is a super trait of Double
    // I.e, all types implementing Double must also implement
    // Debug, and as a consequence:
    // All types implementing Double is ensured to implement
    // Debug.
    trait Double: Debug {
        fn double(&mut self);
    }
    
    impl Double for P<u32> {
        fn double(&mut self) {
            self.x += self.x;
            self.y += self.y;
        }
    }
    
    impl Double for String {
        fn double(&mut self) {
            let s = self.clone();
            self.push_str(&s);
        }
    }
    
    fn main() {
        let mut p1 = P { x: 1u32, y: 2 };
        println!("{:?}", p1);
    
        let mut s = "String, ".to_string();
        println!("{:?}", s);
    
        let mut v: Vec<&mut dyn Double> = Vec::new();
        v.push(&mut p1);
        v.push(&mut s);
    
        for e in &mut v {
            e.double();
            // Here `e` implements Double
            // However we don't know at compile time
            // which implementation (u32 or String)
            // so the compiler will generate
            // a dynamic dispatch.
            //
            // Each `e` will be tagged with a
            // vtable index,
            // and the corresponding `double` function
            // will be called at run time, something like:
            //
            // `Double.vtable[e.vtable_index](e.data)`;
        }
    
        println!("v {:?}", v);
        // Here the Debug::format will be called
        // on each element of v.
        //
        // Since debug is a Super trait of Double
        // The compiler knows that Debug is implemented
        // for each type that implement Double
        // (P<u32> and String)
        //
        // However it does not know at compile time
        // the concrete type of the vector elements,
        // so it uses dynamic dispatch as above.
    }
    
    // Notice, the overhead of dynamic dispatch is
    // merely a pointer indirection, so not a big deal right?
    //
    // Hmmm, not really....
    // The performance kill is likely NOT the additional pointer read
    // but rather that other optimizations are not possible.
    //
    // Relate to the specialization of generics, where
    // function can be inlined and optimized inside of the caller.
    // This is no longer possible.