是否有任何变通办法将带有标记特征的特征对象的Vec转换为没有标记特征的特征对象?

时间:2018-07-30 18:33:31

标签: rust

此代码:

trait Trait {}

fn dont_require_send(ts: Vec<Box<dyn Trait>>) {}

fn use_send(ts: Vec<Box<dyn Trait + Send>>) {
    dont_require_send(ts)
}

失败:

error[E0308]: mismatched types
 --> src/main.rs:6:23
  |
6 |     dont_require_send(ts)
  |                       ^^ expected trait `Trait`, found trait `Trait + std::marker::Send`
  |
  = note: expected type `std::vec::Vec<std::boxed::Box<Trait + 'static>>`
             found type `std::vec::Vec<std::boxed::Box<Trait + std::marker::Send + 'static>>`

我有点理解Rust认为TraitTrait + Send是不同的类型,这可能是导致错误的原因。另一方面,我想不出为什么拒绝此特定代码实际上有用的任何原因。实际上,这很烦人,它迫使我在Send函数的参数中要求dont_require_send,即使该函数实际上并不需要它。在某些情况下,甚至可能使我为这些标记特征的不同组合实现dont_require_send的多个版本。

有什么解决方法吗?还是Rust编译器本身有任何计划使该代码编译?

编辑

我从评论中提取的内容:这个问题与Is there any way to convert Box> to Box>?相同。两种方式都建议在这里解决我的问题。

    如果您可以访问fn dont_require_send<U: Trait + ?Sized>(ts: Vec<Box<dyn U>>) {}的来源,那么
  1. dont_require_send可能是最好的解决方案。我个人不喜欢原来的意图被遮盖,所以我可能很少使用这种新用法。
  2. 如果您无权访问原始源,则可以使用以下方法在呼叫站点转换对象:ts.into_iter().map(|t| t as Box<Trait>).collect();。请注意,仅仅天真地使用另一个问题中的装箱开箱把戏是行不通的(为什么?):dont_require_send(ts.into_iter().map(|t| Box::new(*t)).collect())

0 个答案:

没有答案