Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

rust - How do I implement Ord for a struct?

I've seen a question similar to this one, but no one that tells me exactly how to implement Ord for a struct. For example, the following:

struct SomeNum {
    name: String,
    value: u32,
}

impl Ord for SomeNum {
    fn cmp(&self, other:&Self) -> Ordering {
        let size1 = self.value;
        let size2 = other.value;
        if size1 > size2 {
            Ordering::Less
        }
        if size1 < size2 {
            Ordering::Greater
        }
        Ordering::Equal
    }
}

This gives me the error:

error: the trait `core::cmp::Eq` is not implemented for the type `SomeNum` [E0277]

How would I fix this? I have tried changing the implementation to:

impl Ord for SomeNum where SomeNum: PartialOrd + PartialEq + Eq {...}

and adding the appropriate partial_cmp and eq functions but it gives me the error that both those methods are not a member of Ord.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

The definition of Ord is this:

pub trait Ord: Eq + PartialOrd<Self> {
    fn cmp(&self, other: &Self) -> Ordering;
}

Any type that implements Ord must also implement Eq and PartialOrd<Self>. You must implement these traits for SomeNum.

Incidentally, your implementation looks like being the wrong way round; if self.value is all you are comparing, self.value > other.value should be Greater, not Less.

You can use the Ord implementation on u32 to assist, should you desire it: self.value.cmp(other.value).

You should also take into account that Ord is a total ordering. If your PartialEq implementation, for example, takes name into consideration, your Ord implementation must also. It might be well to use a tuple for convenience (indicating that the most important field in the comparison is value, but that if they are the same, name should be taken into account), something like this:

struct SomeNum {
    name: String,
    value: u32,
}

impl Ord for SomeNum {
    fn cmp(&self, other: &Self) -> Ordering {
        (self.value, &self.name).cmp(&(other.value, &other.name))
    }
}

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

impl PartialEq for SomeNum {
    fn eq(&self, other: &Self) -> bool {
        (self.value, &self.name) == (other.value, &other.name)
    }
}

impl Eq for SomeNum { }

If you’re doing it like this, you might as well reorder the fields and use #[derive]:

#[derive(PartialEq, Eq, PartialOrd, Ord)]
struct SomeNum {
    value: u32,
    name: String,
}

This will expand to basically the same thing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...