Rust 没有两个闭包,即使相同,也具有相同的类型 [duplicate]

Rust no two closures, even if identical, have the same type [duplicate]

提问人:Preston 提问时间:7/31/2023 最后编辑:mkrieger1Preston 更新时间:7/31/2023 访问量:121

问:

如何将两个具有相同定义的闭包放入一个?Vec

下面是一个最小的可重现示例:

fn main() {
    let mut vec = Vec::new();
    vec.push(Box::new(|| println!("test")));
    vec.push(Box::new(|| println!("test2")));
    
    vec.iter().for_each(|f| (f)());
}

编译失败,出现以下错误:

error[E0308]: mismatched types
 --> src/main.rs:4:23
  |
3 |     vec.push(Box::new(|| println!("test")));
  |                       -- the expected closure
4 |     vec.push(Box::new(|| println!("test2")));
  |              -------- ^^^^^^^^^^^^^^^^^^^^ expected closure, found a different closure
  |              |
  |              arguments to this function are incorrect
  |
  = note: expected closure `[closure@src/main.rs:3:23: 3:25]`
             found closure `[closure@src/main.rs:4:23: 4:25]`
  = note: no two closures, even if identical, have the same type
  = help: consider boxing your closure and/or using it as a trait object
防锈 封盖

评论

2赞 Ömer Erden 7/31/2023
需要指出常见的类型,以便生锈可以做强制,.否则 Rust 会假设它像let mut vec: Vec<Box<dyn Fn()>> = Vec::new();Vec<Box<SomeAnonymousConcreteType>>
2赞 cafce25 7/31/2023
找到这个重复的预期关闭,通过将您的标题放入搜索栏找到不同的关闭......
1赞 Preston 7/31/2023
@cafce25在问这个问题之前,我找到了这个问题,但我的问题还没有得到解决方案。

答:

1赞 Aleksander Krauze 7/31/2023 #1

您必须明确告知 holds boxed trait 对象:vec

fn main() {
    let mut vec: Vec<Box<dyn Fn()>> = Vec::new();
    vec.push(Box::new(|| println!("test")));
    vec.push(Box::new(|| println!("test2")));
    
    vec.iter().for_each(|f| (f)());
}

另一方面,您可以保持原样并使用关键字“投射”盒装对象:as

fn main() {
    let mut vec = Vec::new();
    vec.push(Box::new(|| println!("test")) as Box<dyn Fn()>);
    vec.push(Box::new(|| println!("test2")));
    
    vec.iter().for_each(|f| (f)());
}

请注意,您只需要执行一次,因为现在 Rust 会推断出该类型的 is 确实,并且进一步推动将知道自动执行此转换。vecVec<Box<dyn Fn()>>

评论

0赞 PatientPenguin 7/31/2023
我相当确定,您可以向编译器暗示它需要强制,并让它找到正确的类型,而不是给出完整的类型。对于那些所有重要的击键节省as _
0赞 Aleksander Krauze 7/31/2023
@PatientPenguin不幸的是,这不起作用,并会导致以下错误。这是有道理的,因为 rust 无法知道要存储哪些特征对象(、、、或其他完全不同的东西)。an "as" expression can only be used to convert between primitive types or to coerce to a specific trait objectdyn Fn()dyn FnOnce()dyn FnMut()
1赞 PatientPenguin 7/31/2023
哦,你说得完全正确,我的错!
1赞 Masklinn 7/31/2023
@AleksanderKrauze对于这种特殊情况,由于闭包不会关闭任何内容,因此您不必将它们装箱,您可以将它们强制到静态函数指针 ()。fn()