繁体   English   中英

如何在 Rust 中使用方法作为 function 指针

[英]How to use a method as a function pointer in Rust

我有一个 trait 方法需要改变结构的内部数据,我希望我可以将 setter 方法作为参数传递给 trait 方法。 我想这样做,以便通过指定作为参数传递的 function 来灵活处理变异的内容。

这段代码是我想要做的事情的简化,它有相同的编译器问题。

谢谢

代码

struct MyStruct {
    i: usize
}

impl MyStruct {
    fn set_i(mut self, i: usize) -> Self {
        self.i = i;
        self
    }
    fn new() -> Self{
        MyStruct{ i: 0 }
    }
}

trait MyTrait {
    fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> Self ) {
        setter_function(&mut self, 7);
    }
}

impl MyTrait for MyStruct {}


fn main() {
    let mut s = MyStruct::new()
                .set_i(3);
                
    assert_eq!(s.i, 3);
    
    s.do_some_setting(MyStruct::set_i);
    
    assert_eq!(s.i, 7);
}

问题

error[E0308]: mismatched types
  --> src/main.rs:27:23
   |
27 |     s.do_some_setting(MyStruct::set_i);
   |                       ^^^^^^^^^^^^^^^ expected `&mut MyStruct`, found struct `MyStruct`
   |
   = note: expected fn pointer `for<'r> fn(&'r mut MyStruct, _) -> MyStruct`
                 found fn item `fn(MyStruct, _) -> MyStruct {MyStruct::set_i}`

这不起作用,因为MyTrait::do_some_setting需要一个 function ,其第一个参数是&mut Self类型,而MyStruct::set_i的第一个参数是mut self类型。

您可以通过将MyStruct::set_i的签名更改为set_i(&mut self, i: usize)来解决此问题,但是编译器会抱怨mismatched types ,因为它期望MyStruct::set_i返回Self但您会返回&mut Self . 您可以派生Clone并在克隆后返回结构,也可以将签名中的返回类型更改为&mut Self

编译器将再次抱怨类型不匹配,因为setter_function MyTrait::do_some_setting中的 setter_function 是一个 function ,它返回Self ,而不是&mut Self 您必须更改setter_function的签名以返回&mut Self

编译器现在将抱怨在let mut s = MyStruct::new().set_i(3)temporary value dropped while borrowed 您必须先创建MyStruct ,然后在其上使用set_i

最后,您将得到如下所示的代码:

struct MyStruct {
    i: usize,
}

impl MyStruct {
    fn set_i(&mut self, i: usize) -> &mut Self {
        self.i = i;
        self
    }
    fn new() -> Self {
        MyStruct { i: 0 }
    }
}

trait MyTrait {
    fn do_some_setting(&mut self, setter_function: fn(&mut Self, usize) -> &mut Self) {
        setter_function(self, 7);
    }
}

impl MyTrait for MyStruct {}

fn main() {
    let mut s = MyStruct::new();
    s.set_i(3);

    assert_eq!(s.i, 3);

    s.do_some_setting(MyStruct::set_i);

    assert_eq!(s.i, 7);
}

游乐场链接

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM