繁体   English   中英

使用特征作为Vec类型

[英]Use Trait as Vec Type

我是Rust的新手,看到了一些使用Box来允许将实现特定特征的许多类型推送到Vec上的示例。 将特性与泛型一起使用时,我遇到了一个问题。

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.

这是我的代码

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);
    }
}

我正在尝试使用可碰撞对象作为异类游戏对象的列表,这些对象将使我可以与ncollide兼容的Shapes反馈给碰撞检测引擎。

编辑:清除一些混乱。 我不是要构造并返回Trait的实例。 我只是在尝试创建一个Vec,以允许将Collidable特性的任何实例推入该Vec。

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

当你说

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

struct Foo {
   field: Box<MyTrait>
}

您告诉Rust, Foo将包含一个包含任何实现MyTraitbox 通过将类型装箱,编译器将删除特征未涵盖的有关数据类型的所有其他数据。 这些特征对象被实现为一组数据字段和一个函数表(称为vtable ),其中包含该特征公开的函数,因此可以对其进行调用。

当你改变

fn do_thing() -> Box<u32>;

fn do_thing<T>() -> Box<T>;

它可能看起来相似,但是行为却大不相同。 我们来看一个正常的函数示例

fn do_thing<T>(val: T) { }

fn main() {
  do_thing(true);
  do_thing(45 as u32);
}

编译器执行所谓的monomorphization ,这意味着编译器中的代码从本质上变为

fn do_thing_bool(val: bool) { }
fn do_thing_num(val: u32) { }

fn main() {
  do_thing_bool(true);
  do_thing_num(45 as u32);
}

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

用你的代码

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

编译器不知道将使用哪种类型的do_thing进行调用,因此它无法生成需要调用的函数。 为此,无论将实现Collidable的结构转换为盒装对象的任何地方,都必须知道get_ncollide_shape可能具有的每种可能的返回类型,而这不受支持。

其他链接:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM