Specify `Fn` trait bound on struct definition without fixing one of the `Fn` parameters

前端 未结 2 1274
春和景丽
春和景丽 2020-12-11 16:19

I have a struct that contains a function object:

struct Foo {
    func: F,
}

I want to add an Fn trait bound to the s

2条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-11 17:11

    Rather than put constraints on the struct, the simplest and best approach is to put the constraints on the implementation of all methods that will need to use the function:

    struct Foo {
        data: T,
        f: F,
    }
    
    impl Foo {
        fn call_f

    (&self, arg: P) where T: Copy, F: Fn(T, P) { (self.f)(self.data, arg); } }

    First, once the "implied trait bounds" RFC is implemented, this allows me to omit the duplicate trait bounds from all the impl blocks.

    So it sounds like your main concern is about removing duplicate bounds. If that's the problem, you can try to group all the methods with the same bounds into a common impl, so you're still only ever write them once:

    impl Foo 
    where
        T: Copy,
        F: Fn(T, P),
    {
        fn call_f(&self, arg: P) {
            (self.f)(self.data, arg);
        }
    }
    

    There's a little problem here, similar to the one you found yourself: unconstrained type parameter: P. However, now that we've got to here, you can solve it very simply by introducing a trait (you can name it better for your specific use case):

    trait FIsAFunction {
        fn call_f(&self, arg: P);
    }
    
    impl FIsAFunction for Foo 
    where
        T: Copy,
        F: Fn(T, P),
    {
        fn call_f(&self, arg: P){
            (self.f)(self.data, arg);
        }
    }
    

    And users don't have to do anything weird[1]:

    fn main() {
        fn callback(x: u32, y: &str) {
            println!("I was given {:?} and {:?}", x, y)
        }
        let foo = Foo { data: 1u32, f: callback };
        foo.call_f("hello!");
    }
    

    [1] They may have to use the trait. Which isn't so weird: you already have to do that with a lot of std stuff, like std::io::Read etc.

提交回复
热议问题