我试图在里面存储一个 dyn 特征Arc<Mutex<Option<Box<>>>>>,但是由于某种原因它不起作用
Arc<Mutex<Option<Box<>>>>>
use std::sync::{Arc, Mutex}; trait A{} struct B{} impl A for B{} struct H{ c: Arc<Mutex<Option<Box<dyn A>>>> } fn main() { let c = Arc::new(Mutex::new(Some(Box::new(B{})))); H{ c: c }; }
错误:
error[E0308]: mismatched types --> src/main.rs:17:12 | 17 | c: c | ^ expected trait object `dyn A`, found struct `B` | = note: expected struct `Arc<Mutex<Option<Box<(dyn A + 'static)>>>>` found struct `Arc<Mutex<Option<Box<B>>>>`
看起来它不能将 a 存储dyn为 a Box<B>,这很奇怪,因为它有效:
dyn
Box<B>
fn main() { let c: Arc<Mutex<Option<Box<dyn A>>>> = Arc::new(Mutex::new(Some(Box::new(B{})))); }
有什么不同?
Box和其他标准库类型有一个非常特殊的情况,它们可以包含动态大小的值,如dyn A.
Box
dyn A
let c = Arc::new(Mutex::new(Some(Box::new(B{})))); H { c: c };
在此代码中,您已将变量c(没有类型声明)初始化为类型推断为 的值Arc<Mutex<Option<Box<B>>>,然后尝试将其存储在类型为 的字段中Arc<Mutex<Option<Box<dyn A>>>。这是行不通的,因为这两种类型具有不同的内存布局。
c
Arc<Mutex<Option<Box<B>>>
Arc<Mutex<Option<Box<dyn A>>>
let c: Arc<Mutex<Option<Box<dyn A>>>> = Arc::new(Mutex::new(Some(Box::new(B{}))));
在这段代码中,你已经给c一个类型声明,作为结果,其中需要dyn知道在哪里的建造点,这使得胁迫很快发生,你可以强迫一个Box<B>到Box<dyn A>的,因为Box实现了特殊的特质CoerceUnsized. (相同的机制适用于转换&B为&dyn A。)但是,这不适用于包含a 的任意类型Box<B>——甚至不适用Option<Box<B>>,更不用说更复杂的类型了。
Box<dyn A>
CoerceUnsized
&B
&dyn A
Option<Box<B>>
你可以c在构造它时给出一个类型:
let c: Arc<Mutex<Option<Box<dyn A>>>> = Arc::new(Mutex::new(Some(Box::new(B{})))); H { c: c };
或者,稍微短一点但更奇怪,您可以只Box用它需要的类型注释 的直接容器:
let c = Arc::new(Mutex::new(Some::<Box<dyn A>>(Box::new(B{})))); H { c: c };
或者您可以使用as运算符编写显式强制:
as
let c = Arc::new(Mutex::new(Some(Box::new(B{}) as Box<dyn A>))); H { c: c };