admin

强制 Arc<Mutex<Option<Box<MyStruct>>>>> 到 Arc<Mutex<Option<Box<dyn Trait>>>>> 将不起作用

sql

我试图在里面存储一个 dyn 特征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>,这很奇怪,因为它有效:

fn main() {
    let c: Arc<Mutex<Option<Box<dyn A>>>> = 
    Arc::new(Mutex::new(Some(Box::new(B{}))));
}

有什么不同?


阅读 260

收藏
2021-07-01

共1个答案

admin

有什么不同?

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>>>。这是行不通的,因为这两种类型具有不同的内存布局。

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>>,更不用说更复杂的类型了。

你可以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运算符编写显式强制:

let c = Arc::new(Mutex::new(Some(Box::new(B{}) as Box<dyn A>)));
H { c: c };
2021-07-01