![](/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.