2016-02-02 3 views
4

Я пытаюсь проверить равенство двух (функционально идентичных) структур.Проверка равенства пользовательских структур

#[derive(PartialEq, Debug)] 
pub struct TypeA<'a>(&'a str); 

#[derive(PartialEq, Debug)] 
pub struct TypeB<'a>(&'a str); 

impl<'a> TypeA<'a> { 
    pub fn new(n: &str) -> TypeA { 
     TypeA(n) 
    } 
} 

impl<'a> TypeB<'a> { 
    pub fn new(n: &str) -> TypeB { 
     TypeB(n) 
    } 
} 

fn main() { 
    assert_eq!(TypeA::new("A"), TypeB::new("A")); 
} 

возвращает ошибку:

error[E0308]: mismatched types 
    --> src/main.rs:20:5 
    | 
20 |  assert_eq!(TypeA::new("A"), TypeB::new("A")); 
    |  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `TypeA`, found struct `TypeB` 
    | 
    = note: expected type `TypeA<'_>` 
       found type `TypeB<'_>` 
    = note: this error originates in a macro outside of the current crate 

Похоже, получения PartialEq не работает. Это единственное решение для его реализации вручную между этими двумя типами? Проблема в другом месте?

ответ

10

Вывод PartialEq делает работа; но у Руста нет понятия структурного равенства разных типов. Если вы пишете #[derive(PartialEq)] по одному типу, это не означает, что значения этого типа можно сравнить со значениями другого типа, даже если они имеют одинаковую внутреннюю структуру. Это означает только то, что значения этого типа можно сравнить между собой.

Однако PartialEq имеет параметр типа для правой части операнда (творчески именем Rhs), что означает, что вы можете реализовать PartialEq несколько раз для одного типа с различными аргументами типа. #[derive(PartialEq)] будет применять только PartialEq<X>, если применяется на X, но это не мешает вам реализовать PartialEq<Y> для других значений Y самостоятельно.

В этом случае вам необходимо реализовать PartialEq вручную для этих типов, в обоих направлениях:

impl<'a, 'b> PartialEq<TypeB<'b>> for TypeA<'a> { 
    fn eq(&self, other: &TypeB<'b>) -> bool { 
     self.0 == other.0 
    } 
} 

impl<'a, 'b> PartialEq<TypeA<'a>> for TypeB<'b> { 
    fn eq(&self, other: &TypeA<'a>) -> bool { 
     self.0 == other.0 
    } 
} 

После этого вы сможете использовать == или assert_eq!() для этих пар типов. Помните, что вы можете сохранить #[derive(PartialEq)] на своих типах, если вам это тоже нужно!

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