Struct with a generic trait which is also a generic trait

前端 未结 2 756
伪装坚强ぢ
伪装坚强ぢ 2021-01-20 20:57

In Rust 1.15, I have created a trait to abstract over reading & parsing file format(s). I\'m trying to create a struct which has this generic trait inside.

I hav

相关标签:
2条回答
  • 2021-01-20 21:32

    You probably don't want a type parameter, you want an associated type:

    use std::io::Read;
    
    trait MyReader {
        type R: Read;
    
        fn new(Self::R) -> Self;
        fn into_inner(self) -> Self::R;
    
        fn get_next(&mut self) -> Option<u32>;
        fn do_thingie(&mut self);
    }
    
    struct MyIterThing<'a, T>
        where T: MyReader + 'a
    {
        inner: &'a mut T,
    }
    
    fn main() {}
    

    See also:

    • When is it appropriate to use an associated type versus a generic type?
    • Why am I getting "parameter is never used [E0392]"?
    • How can I have an unused type parameter in a struct?
    0 讨论(0)
  • 2021-01-20 21:32

    The error message gives you a suggestion to use a marker, like PhantomData. You can do it like this:

    use std::marker::PhantomData;
    
    struct MyIterThing<'a, R: Read, T: MyReader<R> + 'a> {
        inner: &'a mut T,
        marker: PhantomData<R>,
    }
    

    Instances of PhantomData have zero runtime cost, so it's better to use that than to just create a field of type R.


    Another solution would be to use an associated type instead of a type parameter:

    trait MyReader {
        type Source: Read;
    
        fn new(Self::Source) -> Self;
        fn into_inner(self) -> Self::Source;
    
        fn get_next(&mut self) -> Option<u32>;
        fn do_thingie(&mut self);
    }
    
    struct MyIterThing<'a, T: MyReader + 'a> {
        inner: &'a mut T,
    }
    

    This is a little less flexible as there can only be one choice of Source per implementation of MyReader, but it could be sufficient, depending on your needs.

    0 讨论(0)
提交回复
热议问题