【问题标题】:How can I have an array of Any type?我怎样才能拥有 Any 类型的数组?
【发布时间】:2018-07-30 22:26:15
【问题描述】:

我正在尝试对类似数据框的结构进行建模。我知道如何在这里使用enums,但我正在探索它如何类似于 C#/Python/等。

我尝试关注Rust Trait object conversion,但没有成功:

use std::any::{Any};
use std::fmt::Debug;

pub trait Value: Any + Sized {
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

impl Value for i32 {}

#[derive(Debug)]
struct Frame {
    data: Vec<Box<Any>>,
}

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| Box::new(x.as_any())).collect();
    Frame {
        data: data,
    }
}

编译器抱怨:

error[E0277]: the trait bound `std::vec::Vec<std::boxed::Box<std::any::Any>>: std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not satisfied
  --> src/main.rs:40:61
   |
40 |     let data = of.into_iter().map(|x| Box::new(x.as_any())).collect();
   |                                                             ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<std::any::Any>>` cannot be built from an iterator over elements of type `std::boxed::Box<&std::any::Any>`
   |
   = help: the trait `std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not implemented for `std::vec::Vec<std::boxed::Box<std::any::Any>>`

【问题讨论】:

  • 一个数组与一个Vec不同。
  • 你能解释一下你对错误信息的不理解吗?对我来说似乎很清楚:Box&lt;Any&gt; != Box&lt;&amp;Any&gt;。
  • 请查看如何创建minimal reproducible example,然后查看edit 您的问题以包含它。存在许多与您的问题无关的类型,因此它不是Minimal。
  • @Shepmaster 我了解错误,但不知道如何解决。如果我放 Box::new(x.as_any()) 为什么不匹配 Vec>?
  • 是的,您需要提供足够的代码来重现问题(Complete),但这就是您应该提供的全部内容(Minimal)。如果您阅读minimal reproducible example 的帮助页面,所有这些都会得到解释。

标签: arrays rust generic-programming


【解决方案1】:

主要问题在于这个函数:

fn as_any(&self) -> &Any {
    self
}

这意味着您可以将Value 借用为&amp;Any,(它将&amp;Value 转换为&amp;Any)。

但是,您想从该&amp;Any 创建一个Box&lt;Any&gt;。这永远不会奏效,因为&amp;Any 是借来的值,而Box&lt;Any&gt; 是拥有的。

最简单的解决方案是更改 trait 以返回装箱值(拥有的 trait 对象):

pub trait Value: Any + Sized {
    fn as_boxed_any(&self) -> Box<Any> {
        Box::new(self)
    }
    //The mut variation is not needed
}

现在make_int 函数很简单:

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| x.as_boxed_any()).collect();
    Frame {
        data: data,
    }
}

更新:稍微修改一下,我发现您可以通过以下方式创建Vec&lt;Box&lt;Any&gt;&gt;:

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| Box::new(x) as Box<Any>).collect();
    Frame {
        data: data,
    }
}

如果您只为这种转换编写特征,则实际上不需要它。

【讨论】:

  • 这解决了任务,但奇怪的是为什么 Box::new(x.as_any()) 没有得到相同的效果。
  • @mamcx:正如我所评论的,那是因为as_any() 借用了该值,然后您想获得借用结果的所有权。如果你只想装箱,你可以简单地写fn box_any&lt;T:Any&gt;(t: T) -&gt; Box&lt;Any&gt; { Box::new(t) },然后构建向量:of.into_iter().map(box_any).collect()。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-04
  • 2010-09-25
  • 2021-10-24
  • 2015-09-26
  • 1970-01-01
  • 2012-05-26
相关资源
最近更新 更多