Reputation: 35106
As seen in How can an operator be overloaded for different RHS types and return values? you can implement some operators, eg. Add on multiple types using a work around.
Is a similar thing possible for the PartialEq trait?
I've tried various things, but the closest I can get is creating a fake trait Foo, implementing PartialEq on &Foo (since it's a trait you can't implement it on Foo) and then doing:
let x:Bar = ...
let y:FooBar = ...
if &x as &Foo == &y as &Foo {
...
}
The Equiv trait looks like it should be used for this, but as far as I can tell, implementing Equiv doesn't have anything to do with the == operator.
Is there a way to do this?
Upvotes: 6
Views: 4280
Reputation: 5065
PartialEq
implementations can take any right-hand side typeAs of Rust 1.0.0 (2015), PartialEq
(==
and !=
) allows you to supply any type (sized or not) as the right-hand side's type when you are implementing it. You can also use traits as both the left-hand and right-hand side when implementing PartialEq
.
Implementing PartialEq
for two different types is very simple. The trait PartialEq
takes a generic type called Rhs
that specifies what type you will be comparing with the type that you are implementing PartialEq
for.
impl PartialEq<B> for A {
fn eq(&self, other: &B) -> bool {
/* ... */
}
}
You can use the dyn
1 keyword to specify a trait as a type, which allows us to implement PartialEq
for or with that trait.
trait Foo { /* ... */ }
impl PartialEq<dyn Foo> for dyn Foo {
fn eq(&self, other: &dyn Foo) -> bool {
/* ... */
}
}
==
Below is a working example of writing and testing PartialEq
between two different structs, A
and B
.
struct A {
thing: String,
stuff: u8,
}
struct B {
optional_thing: Option<String>,
extra: String,
}
impl PartialEq<B> for A {
fn eq(&self, other: &B) -> bool {
if let Some(thing_b) = &other.optional_thing {
*thing_b == self.thing
} else {
false
}
}
}
fn main() {
let a1 = A {
thing: "Hello".to_owned(),
stuff: 0,
};
let a2 = A {
thing: "World".to_owned(),
stuff: 32,
};
let b1 = B {
optional_thing: Some("Hello".to_owned()),
extra: "...".to_owned(),
};
let b2 = B {
optional_thing: None,
extra: "".to_owned(),
};
assert!(a1 == b1, "a1 and b1 should be equal");
assert!(a1 != b2, "a1 should not equal b2");
assert!(a2 != b1, "a2 should not equal b1");
assert!(a2 != b2, "a2 should not equal b2");
}
Upvotes: 2
Reputation: 102016
The ==
operator is only overridable via the PartialEq
trait, and thus usable with matching types. Any other form of equality/equivalence needs a custom function/method, you can use the Equiv
trait, although values that are equiv
alent should theoretically also have the same hash (or else HashMap.find_equiv
won't work as you expect).
Upvotes: 5