我想要一个 struct ,Quox,它可以有 Select 地有每种类型的闭包,可以有(FnFnMutFnOnce).我是这样打的:

#[derive(Default, Debug)]
pub struct Quox<Tfn: Fn(&Person) + Sized, Tfnmut: FnMut(&mut Person) + Sized, Tfnonce: FnOnce(&Person) + Sized> {
    soft_closure: Option<Tfn>,
    mut_closure : Option<Tfnmut>,
    move_closure: Option<Tfnonce>,
}

现在,当实例化它时,我通过Box来实现它,因为 rust 蚀投诉the trait Sized is not implemented for `dyn Fn()`rustcE0277.(也许有更好的方法,或者我误解了特征对象?)

pub fn main(){
    let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
        move_closure: None,
        mut_closure : None,
        soft_closure: None,
    };
    ...

}

  1. 真正让我困惑的是,当我创建相应类型的闭包时——为什么我可以随意地将它们赋给qx中的字段:

pub fn main(){
    let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
        move_closure: None,
        mut_closure : None,
        soft_closure: None,
    };


    let greeting  = "Hi. We are moving soon!".to_string();
    let clsr_move = move |p:&Person| println!("Hi, {}. {} says: {}", p.name, p.name, greeting);
    let only_a_ref_clsr = |p:&Person| println!("Hi, {}.",p.name );

 
    // qx.move_closure = Some(Box::new(clsr_move));        // expected
    // qx.soft_closure = Some(Box::new(only_a_ref_clsr));  // expected

    qx.soft_closure = Some(Box::new(clsr_move));           // Why is this valid???
    qx.move_closure = Some(Box::new(only_a_ref_clsr));     // Ok Fn is supertrait to FnOnce

}

同样,令人困惑的是,我try 将(似乎)FnMut分配到Fn并没有出错.


  1. 此外为什么现在将Box赋给中间变量会引发错误???

pub fn main(){
    let mut qx = Quox::<Box<dyn Fn(&Person)>, Box<dyn FnMut(&mut Person)>, Box<dyn FnOnce(&Person)>> {
        move_closure: None,
        mut_closure : None,
        soft_closure: None,
    };


    let greeting  = "Hi. We are moving soon!".to_string();
    let clsr_move = move |p:&Person| println!("Hi, {}. {} says: {}", p.name, p.name, greeting);
    let only_a_ref_clsr = |p:&Person| println!("Hi, {}.",p.name );

    let someboxmove = Some(Box::new(only_a_ref_clsr));
    qx.soft_closure = someboxmove;                         // Invalid. 

}

我得到的错误是:

let someboxmove: Option<Box<|&Person| -> ()>>
Go to Option | Box | Person | Global

mismatched types
expected enum `Option<Box<dyn for<'r> Fn(&'r traitobjects::Person)>>`
   found enum `Option<Box<[closure@src/traitobjects.rs:49:27: 49:66]>>`rustcE0308
traitobjects.rs(49, 27): the found closure
traitobjects.rs(66, 5): expected due to the type of this binding

推荐答案

把你的第一个问题写下来:

let greeting  = "Hi. We are moving soon!".to_string();
let clsr_move = move |p:&Person| println!("Hi, {}. {} says: {}", p.name, p.name, greeting);

let soft_closure: Box<dyn Fn(&Person)> = Some(Box::new(clsr_move));

没有理由clsr_move不等于Fn.move用于告诉编译器将所有捕获into移到闭包中,但使闭包严格意义上FnOnce的是,如果变量移到了闭包的out处.很明显,可以一次又一次地调用这个闭包.


第二个问题只是Rust类型推断的副作用.如果Box::new()应该创建的类型没有立即从表达式中清除,那么它将 Select 给定给它的类型;在后一种情况下,闭包的匿名类型.在前者中,可以看到它将被分配给期望为Box<dyn ...>的对象,并且可以抢先强制该类型.因此,这只是推理算法向前看得不够远的情况.

它也不能隐式地将Option<Box<T>>强制为Option<Box<dyn Trait>>.它可以将Box<T>强制转换为Box<dyn Trait>,但由于尺寸和布局不同,因此不能扩展为Option的通用参数

Rust相关问答推荐

在Rust中宏的表达式中提取对象

S在Cargo.toml中添加工作空间开发依赖关系的正确方法是什么?

如何在Rust中将选项<;选项<;字符串>;转换为选项<;选项&;str>;?

我无法理解Rust范围的定义(Rust Programming Language,第二版克拉布尼克和尼科尔斯)

Rust编译器似乎被结果类型与anyhow混淆

为什么RefCell没有与常规引用相同的作用域?

borrow 是由于对 `std::sync::Mutex>` 的解引用强制而发生的

Rust 中多个 & 符号的内存表示

为什么需要静态生命周期以及在处理 Rust 迭代器时如何缩小它?

在不安全的 Rust 中存储对 struct 内部数据的静态引用是否合法?

有没有办法通过命令获取 Rust crate 的可安装版本列表?

切片不能被 `usize` 索引?

Rust 引用元组和引用元组

为什么 Rust 允许写入不可变的 RwLock?

Rust 中函数的类型同义词

`if let` 只是另一种编写其他 `if` 语句的方式吗?

如果我立即等待,为什么 `tokio::spawn` 需要一个 `'static` 生命周期?

相互调用的递归异步函数:检测到循环

当值是新类型包装器时,对键的奇怪 HashMap 生命周期要求

为什么我在这里得到一个闭包实现`FnMut`,所以对捕获变量的引用不能逃脱闭包?