Not understanding how to overload <, >, etc

I've got a custom GameTime object and am trying to overload the comparison operators for it. I've got == down, but the examples I'm finding for the < and > operators don't make sense to me. For example, from this website: Hand-Implementing PartialEq, Eq, Hash, PartialOrd and Ord in Rust • Phil's Blog

impl PartialOrd for FileInfo {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        self.path.partial_cmp(&other.path)
    }
}

I'm assume this code would work just fine for the one value it's comparing, but this leaves me with two questions.

  1. This function calls partial_cmp, but isn't partial_cmp() what I'm trying to implement? Even if I use that method for each member of the struct, how is the code supposed to know how to properly compare the values?
  2. This comparison looks at only one member, but how the heck am I supposed to use this to compare multiple members on one object? Just call it once for each thing?

Thanks for any help you can give.

It calls partial_cmp on the path field. Essentially it delegates it to the implementation of the field.
If you want to implement it yourself you just have to return how self compares to other, with the possible values being:

  • None if they are not comparable
  • Some(Ordering::Less) if self is less than other
  • Some(Ordering::Equal) if self is equal to other
  • Some(Ordering::Greater) if self is greater than other

(This is just a simple consequence of how Option and Ordering are defined)

If every element is supposed to be comparable with every other element then you can consider implementing Ord and its cmp function and making partial_cmp return Some(self.cmp(other)).

You can write your own logic by looking at what value of Ordering is returned when comparing the fields. If your logic involves knowing how each field of self compare to the relative field of other then you'll have to call partial_cmp once per field.

2 Likes

You are implementing PartialCmp for your own type, which forwards to PartialCmp on another type. Those are not the same function.

I don't get what you are asking there. What code, and what is "properly"?

Use Ordering::and_then.

FYI

I believe the function you're referring to is Ordering::then. Just wanted to chime in since I've wanted this function and didn't find it when I searched for and_then :smile:

4 Likes

Or if you're lazy, you can compare tuples: (left.foo, left.bar).cmp((right.foo, right.bar)), though it probably depends on if the types are Copy or ref-comparable for that to make sense.

1 Like

Aren't types ref-comparable iff they are comparable, due to this blanket impl?

1 Like

Yeah, I just couldn't be bothered to look it up on my phone :yum:

Not sure if this is a typo. In case you mean "if and only if" then no, you can have types that are only ref-comparable but not normally comparable. Rust Playground

That's what I thought, yes.

I thought this would be forbidden as possibly-conflicting with the blanket implementation, but haven't checked myself, so thanks for the correction.

FYI the reason it doesn't conflict with the blanket implementation (at least in my playground example) is that there's no PartialEq/PartialOrd implementation for A and B, so the blanket implementation can't possibly be applied to them.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.