首页 > 解决方案 > 特质有时可以移动

问题描述

我有一个看起来像的特质

trait Trait<T>
    where T: Data
{
    fn m1(&self) -> bool;
    fn m2(self) -> Box<dyn Trait<T>>;
}

为什么甚至允许m2方法?self它不像任何 trait impls 都可以调用该方法,因为:

cannot move a value of type dyn Trait<T>: the size of dyn Trait<T> cannot be statically determined

这个错误是有道理的,但为什么我可以像这样push在容器中描述对象Vec

let trait_object: Box<dyn Trait<T>> = e;
let mut new_vec = Vec::new();
new_vec.push(trait_object)

那么如果特征对象无法移动,为什么会new_vec.push(trait_object)起作用?

标签: rusttraitsmove-semantics

解决方案


dyn Trait<T>是一个 trait 对象,它不同于具有实现该 trait 的约束类型变量。

特征对象使用动态分派并且在编译时不知道大小 - 这就是为什么您几乎总是在&引用或装箱后看到特征对象的原因。这就是错误消息显示的原因the size of dyn Trait<T> cannot be statically determined

您的 trait 可以为任何具体的 ( Sized) 类型实现。例如,对于i32

impl Trait<String> for i32
where
    T: Data,
{
    fn m1(&self) -> bool {
        true
    }

    // Can take self here because i32 is Sized
    fn m2(self) -> Box<dyn Trait2<T>> {
         make_boxed_trait_t(String::new())
    }
}

为什么我可以像这样push在容器中描述对象Vec

这是有效的,因为您的示例中的特征对象是装箱的。dyn Trait<T>没有大小,但Box<dyn Trait<T>>在编译时有一个已知的大小。大小是两个指针的大小,因为装箱的 trait 对象的布局始终是指向数据的指针和指向类型实现的 vtable 的指针Trait


推荐阅读