Home > Software design >  How to have a trait method have a struct argument, in which an item must implement that same trait?
How to have a trait method have a struct argument, in which an item must implement that same trait?

Time:06-07

I have a struct Lambertian:

pub struct Lambertian {
    albedo: Color,
}

A Material trait with an associated method:

pub trait Material {
    fn scatter(&self, ray: &Ray, rec: &HitRecord) -> Option<(Ray, Color)>;
}

And finally, another struct that holds a value of something that implements the Material trait

pub struct HitRecord<T>
where T: Material
{
    // snip
    pub mat_ptr: Rc<T>,
}

So, I want the generic T in HitRecord to implement Material, but I have a parameter of type HitRecord in the trait method scatter. To make this work, I have to annotate Material with another T, then specifying that that T implements Material as well... Hence doing a recursive definition. What do I need to do instead ?

CodePudding user response:

You can put the generic on the scatter method rather than Material:

pub trait Material {
    fn scatter<T>(&self, ray: &Ray, rec: &HitRecord<T>) -> Option<(Ray, Color)>
    where
        T: Material;
}

Or if you want rec to use the same material type as self, make the generic argument Self:

pub trait Material {
    fn scatter(&self, ray: &Ray, rec: &HitRecord<Self>) -> Option<(Ray, Color)>;
}

This requires relaxing the constraint Sized constraint on HitRecord<T>:

pub struct HitRecord<T>
where
    T: Material   ?Sized,
  • Related