2015-04-26 3 views
11

Я видел вопрос, похожий на этот, но не тот, который подсказывает мне, как реализовать 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

* Я видел вопрос, подобный этому, но * - пожалуйста ** включите ссылки на эти вопросы **, как только вы их найдете. Это позволяет ответчикам лучше понять, какие объяснения вы уже прочитали, которые не имеют смысла, иначе мы рискуем просто повторить то же самое, что вы уже знаете, тратя время на все! Это также хорошо для будущих искателей, поскольку они могут легко перейти к связанным вопросам. – Shepmaster

ответ

20

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

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

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

Кстати, ваша реализация выглядит как неправильный путь; if 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, 
} 

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

+0

Спасибо! Еще кое-что. Если бы я хотел вручную вычислить cmp, что бы я вернулся, чтобы обозначить больше, меньше или равно. Я попытался сделать это и возвратить Ordering :: Less, Ordering :: Greater и Ordering :: Equal, если это необходимо, но компилятор заявляет, что cmp ожидает тип вывода() вместо core :: cmp :: Ordering. Кажется, это происходит только в случаях «Меньше» и «Больших», которые встречаются в выражении if – Dumbapples

+1

О, да, что вы хотели, было «if size1 size2 {Ordering :: Greater} else { Заказ :: Равный}.Выражение 'if' имеет тип, у вас было фактически три оператора в строке, значения первых двух из которых не использовались и которые также имели непоследовательные типы, поскольку они имели неявный' else {} ', который имеет тип '()'. –

+0

Справа. Еще раз спасибо! – Dumbapples

Смежные вопросы