3

I'm writing a ray-tracer to learn Rust. I've got a Scene which contains Shapes, shapes that can intersect rays. Minimally, it is akin to:

pub trait Shape {
    fn draw(&self);
}

pub struct Plane {}

impl Shape for Plane {
    fn draw(&self) {}
}

pub struct Sphere {}

impl Shape for Sphere {
    fn draw(&self) {}
}

pub struct Scene {
    objects: Vec<Box<dyn Shape>>,
}

fn main() {
    let mut scene = Scene { objects: vec![] };

    let plane1 = Box::new(Plane {});
    let plane2 = Box::new(Plane {});
    let sphere = Box::new(Sphere {});

    scene.objects.push(plane1);
    scene.objects.push(plane2);
    scene.objects.push(sphere);

    for object in scene.objects {
        // I want to test if a given object in the scene is the same as another
        if object == plane2 {}
    }
}

Given a shape stored in Vec<Box<dyn Shape>> how can I test equality to a given boxed object implementing the Shape trait?

error[E0369]: binary operation `==` cannot be applied to type `std::boxed::Box<Shape>`
  --> src/main.rs:34:12
   |
34 |         if object == plane2 {}
   |            ^^^^^^^^^^^^^^^^
   |
   = note: an implementation of `std::cmp::PartialEq` might be missing for `std::boxed::Box<Shape>`

The test will be done in a Sphere or Plane member function, testing against self.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Jeffrey
  • 11,063
  • 1
  • 21
  • 42
  • Why do you use raw pointer, your question is not clear please do a proper [mcve], `self` is a `Sphere` not a `Box` so why did you expect ? – Stargateur Sep 10 '18 at 23:06
  • Maybe you want `pub fn some_function(&self, intersector: &T) where T: Intersector` ? – Stargateur Sep 10 '18 at 23:12
  • @Shepmaster thanks. Rewritten in MCVE form. I have diffuclty understanding the answers you linked to. Is there a simpler answer with this now clear question? – Jeffrey Sep 11 '18 at 15:15
  • 1
    Based on your latest changes, [How to test for equality between trait objects?](https://stackoverflow.com/q/25339603/155423) appears to be the duplicate. – Shepmaster Sep 11 '18 at 17:19
  • Does `plane1 == plane2`? – trent Sep 11 '18 at 17:32
  • 1
    @Shepmaster thanks! Please mark as duplicate. – Jeffrey Sep 11 '18 at 18:29

1 Answers1

1

In C++, you can convert from a pointer to a Sphere to a pointer to an Intersector (ie. from a Sphere* to an Intersector*). It also works with references although this is less idiomatic for C++.

This is exactly the same in Rust, except that in Rust it is more idiomatic to use references rather than raw pointers:

impl Scene {
    pub fn some_function(&self, intersector: &Intersector) {
        for object in &self.objects {
            if intersector == object {}
        }
    }
}

Note that your original code used *const Box<dyn Intersector> which is a pointer to a box containing an Intersector and translates roughly to smart_pointer<Intersector>* in C++, so your Rust code would be equivalent to passing an Intersector* to a function expecting a smart_pointer<Intersector>*, which doesn't work in C++ either.

Jmb
  • 18,893
  • 2
  • 28
  • 55
  • I'd rather understand how to do it with the boxed object than restart with a different architecture. And in C++, you can easily do if (scene[0].get() == sphere) – Jeffrey Sep 11 '18 at 15:49