预期关闭,发现不同的关闭 [英] Expected closure, found a different closure

查看:55
本文介绍了预期关闭,发现不同的关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

A 是一个包含 B 向量的结构.A 实现了 add_b 方法,该方法将 B 实例添加到 B 的列表中.B 包含一个闭包属性 f.

A is a structure which contains a vector of B. A implements the add_b method which adds a B instance to the list of B. B contains a closure property f.

如果我用 add_b 在向量中添加一个 B,就可以了.如果我用 add_b 添加两个向量,我会收到一个错误消息,说这两个闭包不同.这是一个最小的例子:

If I add one B to the vector with add_b, it's OK. If I add two vectors with add_b, I got an error saying the two closures are different. Here is a minimal example:

// A struct...
struct A<F> {
    b_vec: Vec<B<F>>, // A vector of B
}

// ...and its implementation
impl<F> A<F>
where
    F: Fn(),
{
    fn new() -> A<F> {
        A { b_vec: Vec::new() }
    }

    fn add_b(&mut self, b: B<F>) {
        self.b_vec.push(b);
    }
}

// B struct...
struct B<F> {
    f: F,
}

// ...and its implementation
impl<F> B<F>
where
    F: Fn(),
{
    fn new(f: F) -> B<F> {
        B { f: f }
    }
}

// I add two B (with their closures arguments) in A
fn main() {
    let mut a = A::new();
    a.add_b(B::new(|| println!("test")));
    a.add_b(B::new(|| println!("test2")));
}

此代码导致:

error[E0308]: mismatched types
  --> src/main.rs:39:20
   |
39 |     a.add_b(B::new(|| println!("test2")));
   |                    ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
   |

如何将多个具有不同闭包的 B 添加到 Ab_vec 中?

How can I add multiple B with their different closures to A's b_vec?

推荐答案

完整 编译器输出总是值得一看的:

It's always worth taking a look at the full compiler output:

error[E0308]: mismatched types
  --> src/main.rs:39:20
   |
39 |     a.add_b(B::new(|| println!("test2")));
   |                    ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
   |
   = note: expected type `[closure@src/main.rs:38:20: 38:39]`
              found type `[closure@src/main.rs:39:20: 39:40]`
   = note: no two closures, even if identical, have the same type
   = help: consider boxing your closure and/or using it as a trait object

特别有帮助:

没有两个闭包,即使相同,也没有相同的类型

no two closures, even if identical, have the same type

  • 考虑装箱您的闭包和/或将其用作特征对象

    consider boxing your closure and/or using it as a trait object

  • 我们可以通过完全删除类型 B 来进一步简化您的示例.那么唯一的任务就是保存一个闭包向量.正如编译器告诉我们的,没有两个闭包具有相同的类型,但是 Vec 是一个同构的数据结构,这意味着其中的每个项目都具有相同的类型.

    We can simplify your example further by removing the type B altogether. Then the only task is to save a vector of closures. As the compiler tells us, no two closures have the same type, but Vec is a homogeneous data structure, meaning that every item in it has the same type.

    我们可以通过引入一层间接来解决这个限制.正如编译器所建议的那样,这可以通过特征对象或装箱来完成(后一种包括第一种).相应的类型如下所示:

    We can work around that restriction by introducing one level of indirection. As the compiler suggests, this can either be done by trait objects or boxing (the latter kind of includes the first one). The corresponding types would look like this:

    • Vec<&Fn()>(对特征对象的引用)
    • Vec>(盒子中的特征对象)
    • Vec<&Fn()> (reference to trait objects)
    • Vec<Box<Fn()>> (trait object in a box)

    在您的示例中,您希望 拥有 所有闭包,因此正确的选择是将所有闭包装箱,因为 Box 是一个拥有包装器,而引用仅借用东西.

    In your example you want to own all closures, thus the correct choice is to box all closures, as Box<T> is an owning wrapper while references only borrow stuff.

    一个完整的例子:

    struct A {
        b_vec: Vec<B>,
    }
    
    impl A {
        fn new() -> A {
            A { b_vec: Vec::new() }
        }
    
        fn add_b(&mut self, b: B) {
            self.b_vec.push(b);
        }
    }
    
    struct B {
        f: Box<Fn()>,
    }
    
    impl B {
        fn new<F>(f: F) -> B
        where
            F: Fn() + 'static,
        {
            B { f: Box::new(f) }
        }
    }
    
    fn main() {
        let mut a = A::new();
        a.add_b(B::new(|| println!("test")));
        a.add_b(B::new(|| println!("test2")));
    }
    

    这篇关于预期关闭,发现不同的关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆