Rust 使用Trait作为Vec类型

Rust 使用Trait作为Vec类型,rust,Rust,我是个新手,见过一些人使用Box将实现某种特性的多种类型推到Vec上的例子。在泛型中使用Trait时,我遇到了一个问题 error[E0038]: the trait `collision::collision_detection::Collidable` cannot be made into an object --> src/collision/collision_detection.rs:19:5 | 19 | collidables: Vec<Box<

我是个新手,见过一些人使用Box将实现某种特性的多种类型推到Vec上的例子。在泛型中使用Trait时,我遇到了一个问题

error[E0038]: the trait `collision::collision_detection::Collidable` cannot be made into an object
  --> src/collision/collision_detection.rs:19:5
   |
19 |     collidables: Vec<Box<Collidable<P, M>>>,
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `collision::collision_detection::Collidable` cannot be made into an object
   |
   = note: method `get_ncollide_shape` has generic type parameters

error: aborting due to previous error

error: Could not compile `game_proto`.

To learn more, run the command again with --verbose.
error[E0038]:无法将特征'collision::collision\u detection::collisable'生成对象
-->src/碰撞/碰撞检测。rs:19:5
|
19 |可碰撞:Vec,
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^无法将特征“碰撞::碰撞检测::可碰撞”制成对象
|
=注意:方法“get\u ncollide\u shape”具有泛型类型参数
错误:由于上一个错误而中止
错误:无法编译“game\u proto”。
要了解更多信息,请使用--verbose再次运行该命令。
这是我的密码

extern crate ncollide;
extern crate nalgebra as na;

use self::ncollide::shape::Shape;
use self::ncollide::math::Point;
use self::ncollide::math::Isometry;
use self::na::Isometry2;

pub trait Collidable<P: Point, M> {
    fn get_ncollide_shape<T: Shape<P, M>>(&self) -> Box<T>;
    fn get_isometry(&self) -> Isometry2<f64>;
}

pub struct CollisionRegistry<P, M>
where
    P: Point,
    M: Isometry<P>,
{
    collidables: Vec<Box<Collidable<P, M>>>,
}

impl<P: Point, M: Isometry<P>> CollisionRegistry<P, M> {
    pub fn new() -> Self {
        let objs: Vec<Box<Collidable<P, M>>> = Vec::new();
        CollisionRegistry { collidables: objs }
    }

    pub fn register<D>(&mut self, obj: Box<D>)
    where
        D: Collidable<P, M>,
    {
        self.collidables.push(obj);
    }
}
extern-craten-ncollide;
外部板条箱nalgebra为na;
使用self::ncollide::shape::shape;
使用self::ncollide::math::Point;
使用self::ncollide::math::Isometry;
使用self::na::Isometry2;
可碰撞的{
fn获得圆形(&self)->长方体;
fn获取_等距(&self)->Isometry2;
}
发布结构冲突注册表
哪里
P:重点,
M:等距

, { 可碰撞:Vec, } impl冲突注册表{ pub fn new()->Self{ 让objs:Vec=Vec::new(); 碰撞注册表{collidables:objs} } 发布fn寄存器(&mut self,obj:Box) 哪里 D:可碰撞, { 自碰撞推(obj); } }

我正在尝试使用collidables作为一个异构游戏对象列表,它将为我提供与ncollide兼容的形状,以反馈给碰撞检测引擎

编辑:
澄清一些混乱。我并不是试图构造并返回一个Trait的实例。我只是想创建一个Vec,它允许将可碰撞特征的任何实例推送到它上面。

Rust是一种编译语言,所以当它编译代码时,它需要知道生成机器代码可能需要的所有信息

当你说

trait MyTrait {
  fn do_thing() -> Box<u32>;
}

struct Foo {
   field: Box<MyTrait>
}

要意识到的关键是,你要求它对你的特质做同样的事情。问题是编译器不能这样做。上面的例子依赖于提前知道
do_thing
在一种情况下是用数字调用的,在另一种情况下是用布尔值调用的,并且它可以100%确定地知道这是函数使用的唯一两种方式

用你的代码

trait MyTrait {
  fn do_thing<T>() -> Box<T>;
}
trait-MyTrait{
fn do_thing()->Box;
}
编译器不知道将使用什么类型调用
do\u thing
,因此无法生成需要调用的函数。要做到这一点,无论您在何处将实现
可碰撞的
的结构转换为装箱对象,都必须知道
get\u ncollide\u shape
可能具有的所有可能的返回类型,而这是不受支持的

其他链接:


可能的副本可能有更好的副本,但类似。@loganfsmyth这不是我想做的。我已经阅读了大多数与此类似的示例,并通过使用Vec使它们正常工作。但是当我使用一个像Vec这样的泛型特征时,我突然发现了这个错误。你期望
get\u ncollide\u shape
做什么?这个错误是因为
Box
意味着基本上你已经删除了一个对象的所有数据,除了它实现了一个特征。在这种情况下,
fn get\u ncollide\u shape(&self)->Box没有意义,因为无法调用它。该函数有无限多个版本,因为它在
T
上是参数化的,所以无法使用该函数,因为它需要在运行时决定调用哪个版本,并且选项是已知的。@loganfsmyth我不确定您真正的意思。该部分只返回实现形状特征的任何对象。这部分代码经过编译,到目前为止似乎还不错。在错误消息中,它引用第19行(在结构定义中)作为问题。你对这部分有什么想法吗?错误在第19行,因为这是你声明trait的盒装版本的地方。错误显示为“注意:方法
get\u ncollide\u shape
具有泛型类型参数”,因为在将装箱的特征上不允许使用类似
get\u ncollide\u shape
的泛型参数。Rust是一种编译语言,因此它需要能够创建代码来执行您的请求,而它不能执行您的请求。
fn do_thing<T>() -> Box<T>;
fn do_thing<T>(val: T) { }

fn main() {
  do_thing(true);
  do_thing(45 as u32);
}
fn do_thing_bool(val: bool) { }
fn do_thing_num(val: u32) { }

fn main() {
  do_thing_bool(true);
  do_thing_num(45 as u32);
}
trait MyTrait {
  fn do_thing<T>() -> Box<T>;
}