Partly use derive PartialEq


#1

I have struct with several fields one of them is f64. I want to compare this field with (a.f -b.f).abs() < eps and reuse auto genetated code by derive(ParialEq) for comparing other field, is it possible somehow?


#2

No, you have to implement PartialEq yourself for your struct. Of course you can defer to the existing PartialEq implementations for the fields which have those, but you would have to do that manually.


#3

Actually, there is a nice pattern to do this, though it won’t save a lot of typing in this case. You can define a local struct and reuse it’s derive:

struct Bad {
    x: i32,
    y: String,
    z: f64
}

impl PartialEq for Bad {
    fn eq(&self, other: &Bad) -> bool {
        #[derive(PartialEq)]
        struct Good<'a> {
            x: &'a i32,
            y: &'a String,
        }

        fn to_good(bad: &Bad) -> Good { Good { x: &bad.x, y: &bad.y } }

        assert!(!self.z.is_nan() && !other.z.is_nan());

        to_good(self) == to_good(other) && self.z == other.z
    }
}

And keep in mind that (x - y).abs() < eps is not an equivalence relation on floats.


#4

Another, more succinct alternative is to wrap all f64’s in a MyFloat struct for which you can define PartialEq however you want. And then you can #[derive(PartialEq)] on structs containing instances of MyFloat.

struct MyFloat(f64);

impl PartialEq for MyFloat {
    fn eq(&self, other: &MyFloat) -> bool {
        // ..
    }
}

#[derive(PartialEq)]
struct MyStruct {
    x: i32,
    y: String,
    z: MyFloat,
}

Playground

The only drawback is that you would have to refer to the float as my_struct.z.0 instead of my_struct.z.