![](/img/trans.png)
[英]Why does a trait type `Box<dyn Error>` error with "Sized is not implemented" but `async fn() -> Result<(), Box<dyn Error>>` works?
[英]Does `Box` obscure trait bounds? Why can i assign `dyn FnOnce()` to `dyn Fn()` in this case?
我想要一个结构Quox
,它可以有选择地拥有周围可能存在的每种类型的闭包( Fn
、 FnMut
和FnOnce
)。 我是这样输入的:
#[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,
};
...
}
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
}
同样,令人困惑的是,我在尝试将(看似) FnMut
分配给Fn
时没有收到任何错误。
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
是为了告诉编译器将所有捕获移动到闭包中,但是严格FnOnce
的闭包是变量是否被移出闭包。 这个闭包显然可以被一次又一次地调用。
你的第二个问题只是 Rust 类型推断的副作用。 如果Box::new()
应该创建的类型不能立即从表达式中明确,那么它将选择给它的类型; 在后一种情况下,闭包的匿名类型。 在前者中,它可以看到它将被分配给期望Box<dyn...>
的东西并且可以抢先强制类型。 所以很简单,推理算法看得不够远。
它也不能隐式地将Option<Box<T>>
强制转换为Option<Box<dyn Trait>>
。 它可以将Box<T>
强制转换为Box<dyn Trait>
,但由于它们具有不同的大小和布局,因此它不会扩展为Option
的通用参数
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.