如何用数组填充trait对象向量?解析Rust代码报错及无克隆方案
Rust数组转Trait对象Vec的错误原因及无克隆解决方法
问题代码
trait Foo {} struct Fooable {} impl Foo for Fooable {} pub fn main() { let bar: Vec<Box<dyn Foo>> = [ Box::new(Fooable {}), ].into(); }
错误信息
error[E0277]: the trait bound `Vec<Box<dyn Foo>>: From<[Box<Fooable>; 1]>` is not satisfied --> src/main.rs:10:7 | 10 | ].into(); | ^^^^ the trait `From<[Box<Fooable>; 1]>` is not implemented for `Vec<Box<dyn Foo>>` | = help: the following other types implement trait `From<T>`: <Vec<T, A> as From<Box<[T], A>>> <Vec<T, A> as From<VecDeque<T, A>>> <Vec<T> as From<&[T]>> <Vec<T> as From<&mut [T]>> <Vec<T> as From<BinaryHeap<T>>> <Vec<T> as From<Cow<'a, [T]>>> <Vec<T> as From<[T; N]>> <Vec<u8> as From<&str>> and 2 others = note: required because of the requirements on the impl of `Into<Vec<Box<dyn Foo>>>` for `[Box<Fooable>; 1]`
错误原因
- Rust标准库中
Vec<T>的From<[T; N]>全局实现要求输入数组的元素类型与Vec的元素类型完全匹配。这里数组元素是Box<Fooable>(具体类型指针),而目标Vec的元素是Box<dyn Foo>(trait对象指针),二者属于不同类型,Rust不会自动隐式批量转换数组元素类型来满足Fromtrait的约束。 .into()方法依赖Intotrait,而Into的默认实现又依赖对应的From实现,因此当目标类型的From不存在时,Into调用就会失败。
无克隆解决方法
以下几种方式都不需要克隆Fooable实例,仅做零成本的类型转换:
方法1:转换元素后收集为Vec
通过into_iter()遍历数组,将每个元素转换为trait对象指针,再收集成目标Vec:
pub fn main() { let bar: Vec<Box<dyn Foo>> = [Box::new(Fooable {})] .into_iter() .map(|b| b as Box<dyn Foo>) .collect(); }
这里的as转换是零成本的,仅调整指针的元数据,不会拷贝或克隆Fooable实例。
方法2:直接初始化目标Vec
跳过数组转Vec的步骤,直接创建包含trait对象指针的Vec:
pub fn main() { let bar = vec![Box::new(Fooable {}) as Box<dyn Foo>]; }
方法3:先转同类型Vec再转换元素(Rust 1.63+)
利用数组的into_vec()方法先转成同类型Vec,再转换元素类型:
pub fn main() { let bar: Vec<Box<dyn Foo>> = [Box::new(Fooable {})] .into_vec() .into_iter() .map(|b| b as Box<dyn Foo>) .collect(); }
内容的提问来源于stack exchange,提问作者frankplow
相关产品推荐
相关产品推荐

