Как мне реализовать Ord для структуры?

Я видел вопрос, похожий на этот, но никто не говорит мне, как именно реализовать Ord для структуры. Например, следующее:

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
    }
}

Это дает мне ошибку:

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

Как бы я это исправить? Я попытался изменить реализацию на:

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

и добавив соответствующий partial_cmp а также eq функции, но это дает мне ошибку, что оба эти метода не являются членами Ord,

1 ответ

Решение

Определение Ord это:

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

Любой тип, который реализует Ord должен также реализовать Eq а также PartialOrd<Self>, Вы должны реализовать эти черты для SomeNum,

Между прочим, ваша реализация выглядит неправильно; если self.value это все, что вы сравниваете, self.value > other.value должно быть Greater не Less,

Вы можете использовать Ord реализация на u32 чтобы помочь, если вы хотите этого: self.value.cmp(other.value),

Вы также должны принять во внимание, что Ord это полный порядок. Если твой PartialEq реализация, например, занимает name принимая во внимание, ваш Ord реализация должна также. Для удобства целесообразно использовать кортеж (что указывает на то, что наиболее важным полем в сравнении является value, но если они одинаковы, name следует учитывать), как то так:

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 { }

Если вы делаете это так, вы можете также изменить порядок полей и использовать #[derive]:

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

Это расширится в основном до того же самого.

Другие вопросы по тегам