Подтвердить что ты не робот

Как реализовать 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.

4b9b3361

Ответ 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,
}

Это будет распространяться на одно и то же.