rust - 你如何创建一个 Box<dyn Trait>,或者一般情况下一个装箱的未调整大小的值?

标签 rust trait-objects

我有以下代码

extern crate rand;
use rand::Rng;

pub struct Randomizer {
    rand: Box<Rng>,
}

impl Randomizer {
    fn new() -> Self {
        let mut r = Box::new(rand::thread_rng()); // works
        let mut cr = Randomizer { rand: r };
        cr
    }

    fn with_rng(rng: &Rng) -> Self {
        let mut r = Box::new(*rng); // doesn't work
        let mut cr = Randomizer { rand: r };
        cr
    }
}

fn main() {}

它提示

error[E0277]: the trait bound `rand::Rng: std::marker::Sized` is not satisfied
  --> src/main.rs:16:21
   |
16 |         let mut r = Box::new(*rng);
   |                     ^^^^^^^^ `rand::Rng` does not have a constant size known at compile-time
   |
   = help: the trait `std::marker::Sized` is not implemented for `rand::Rng`
   = note: required by `<std::boxed::Box<T>>::new`

我不明白为什么需要 SizedRng什么时候Box<T>不会将此强加于 T .

最佳答案

关于 Sized 特性和边界的更多信息 - 这是一个相当特殊的特性,即 implicitly added每个函数,这就是为什么你没有在 Box::new 的原型(prototype)中看到它的原因:

fn new(x: T) -> Box<T>

请注意,它按值(或移动)获取 x,因此您需要知道它有多大才能调用该函数。

相比之下,Box 类型本身 需要Sized;它使用(再次特殊的)特性绑定(bind) ?Sized,这意味着“选择退出默认的 Sized 绑定(bind)”:

pub struct Box<T> where T: ?Sized(_);

如果仔细查看,有一种方法可以创建类型未调整大小的 Box:

impl<T> Box<T> where T: ?Sized
....
    unsafe fn from_raw(raw: *mut T) -> Box<T>

所以从不安全的代码,你可以从一个原始指针创建一个。从那时起,所有正常的事情都会起作用。

关于rust - 你如何创建一个 Box<dyn Trait>,或者一般情况下一个装箱的未调整大小的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39216874/

相关文章:

memory-management - 如何将 Box<dyn Trait> 转换为 Rc<dyn Trait>?

generics - 为什么 `&(?Sized + Trait)`无法转换为 `&dyn Trait`?

rust - 如何使用 dyn 类型别名将生命周期参数添加到 Box<>

rust - 如何让 Cargo 运行本地依赖项的测试?

enums - 如何读取与 Rust 中的自定义类型关联的枚举值?

rust - 我为什么要使用不同的功能?

rust - 在 Rust 中使用泛型、特征别名和构造函数

函数指针与 Fn 特征对象

vector - 如何使用 wasm-bindgen 将 Vec 作为类型化数组返回?

rust - 借用检查器和共享 I/O